特定の文字が表示されるまですべての文字を置き換えます。

特定の文字が表示されるまですべての文字を置き換えます。

例えば、以下は md5sum コマンドの出力です。

35c9581c469c366e286be708a9d9f939  input.txt

これは私が実行しているコマンドラインです。

md5sum input.txt | sed -f script.sed

md5sumの出力は次のようになります。

35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx  input.txt

現在、私の.sedスクリプトには、最初の4文字を除くすべての内容を編集する次の内容が含まれています。

s/./x/5g

スペース「」が見つかったら、この操作を停止する必要があります。どんなアイデアがありますか?

答え1

if(md5sum) hash;これはこれを行います(中括弧拡張をサポートするシェルで)。

sed -e's/./x/'{5..32} infile

else 最初の文字スペースが表示されるまで、すべての文字長に対して以下を行います。

sed一般的な解決策として、およびを使用してください。

sed -E ':a s/^(.{4}x{0,})[^x ]/\1x/;ta' infile
  • :ased私たちの名前付きタグa
  • s/以下の一致を交換してください。
    • ^行アンカーポイントの始まりです。
    • (グループ予選開始
      • .単一文字の一致
      • .{4}4文字(または....)のみが一致し、次の文字と一致します。
      • x{0,}0文字以上x(またはx*
    • )グループマッチが終了し、リバース参照は\1
    • [^x ]文字列を除くすべての文字と一致しますx(文字クラスでその^文字が開かれた直後に最初の文字の場合は、否定一致が行われます。)[[^...]
  • /以下で
    • \1は上記の一致部分の逆参照である(...)ため、最初の部分は再び所定の位置にありますが、x後で追加のコンテンツが追加されます。
    • そして一つ、上で私たちは別れ予選で得点できxなかったという事実を覚えていますか?今一つずつ入れ替えるキャラクターたちです。[^x ](...)x
  • /交換終了
  • ;新しいコマンドの開始
  • taa交換が成功するとラベルに移動します。それ以外の場合は、すべての文字を次のように置き換えました。これは、置き換えてコマンドをx終了する文字が残っていないことを意味します。sed

答え2

md5sumハッシュに対して常に32文字の出力を生成します。スペースを検索する代わりに、32文字を検索してからスペースを検索し、最後の28文字をXに置き換えることができます。

md5sum input.txt | sed -E 's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
35c9xxxxxxxxxxxxxxxxxxxxxxxxxxxx  input.txt

分解の説明:

's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'

's/A                                  / B                             /'
we're substituting patterns matching A with B

's/  [[:xdigit:]]    [[:xdigit:]]     /                               /'
we're looking for two groups of hexadecimal characters

's/  [[:xdigit:]]{4} [[:xdigit:]]{28} /                               /'
The first group has exactly four characters
The second group has exactly twenty-eight characters

's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /                               /'
The first group is a "capture group" which we can reference later

's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1                             /'
We will print out the first group verbatim in the output

's/ ([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
We will print x's followed by a space for the next 28 characters

's/^([[:xdigit:]]{4})[[:xdigit:]]{28} /\1xxxxxxxxxxxxxxxxxxxxxxxxxxxx /'
The statement must appear at the start of a line and have a space at the end.

答え3

パール方法:

$ md5sum file | perl -ple 's/^(.{4})(\S+)(\s+.*)/$1 . "x" x length($2) . $3/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx  file

最初の 4 文字 ( ^(.{4})) を検索し、空白以外の文字をできるだけ多く ( (\S+))、最初の文字以上の空白を検索し、行末まですべての項目 ( (\s+.*)) を検索します。その後、最初のキャプチャされた値($1、最初の4文字)に置き換えられ、これはx2番目のキャプチャされたグループ()の長さだけ繰り返され"x" x length($2)、最後のキャプチャされたグループが続きます$3/eを計算するには、演算子の末尾に置換が必要ですs///

md5sumもちろん、常に実行されるので、ハッシュ長さ(4)が常に28になることを知っていれば、次のように単純化できます。

$ md5sum file | perl -ple 's/^(.{4})(\S+)/$1 . "x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx  file

でも:

$ md5sum file | perl -ple 's/(?<=.{4})(\S+)/"x" x 28/e'
9191xxxxxxxxxxxxxxxxxxxxxxxxxxxx  file

答え4

$ md5sum somefile
d68610fdffd770de94818268899d6abb  somefile
$ md5sum somefile | { read -r hash pathname; printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx  %s\n' "$hash" "$pathname" }
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx  somefile

これはハッシュとパス名を2つのシェル変数として読み取り、それを印刷してハッシュの最後の28文字を置き換えますx

複数のファイルをサポートするにはループを使用してください。

$ md5sum somefile* | while read -r hash pathname; do printf '%.4sxxxxxxxxxxxxxxxxxxxxxxxxxxxx  %s\n' "$hash" "$pathname"; done
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx  somefile
d686xxxxxxxxxxxxxxxxxxxxxxxxxxxx  somefile1
d41dxxxxxxxxxxxxxxxxxxxxxxxxxxxx  somefile2

関連情報