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