次を書き換えるsed
(または両方)作成する方法:awk
echo 'v100 v201 v102 v300 v301 v500 v999 v301' | sed/awk ...
この出力に:
v1 v2 v3 v4 v5 v6 v7 v5
つまり、各後続の項目はvx
最初から書き直され、同じ項目がシーケンスで使用される場合v1...vn
(つまり)同じ項目が適用される必要があります。v
v301
v
v5
注:入力シーケンスの例は、可能なすべての例(重複、順序が正しくないソースデータ、ソース番号ジャンプ)を示しています。
この質問に答えることができるsedまたはawkの専門家ですか?
答え1
使用awk
:
awk '{ for (i=1; i<=NF; ++i) $i = (seen[$i] ? seen[$i] : seen[$i] = "v" ++n) }; 1'
その後、各入力行のすべてのフィールドを繰り返し再割り当てします。再割り当てされた値v
の後には、カウンタの次の値が続きますn
。ただし、フィールド値が以前に確認されなかった場合、新しい値は以前に提供されたフィールド値と同じです。
最後1
の項目は変更された行の出力をトリガーします。
テスト:
$ echo 'v100 v201 v102 v300 v301 v500 v999 v301' | awk '{ for (i=1; i<=NF; ++i) $i = (seen[$i] ? seen[$i] : seen[$i] = "v" ++n) }; 1'
v1 v2 v3 v4 v5 v6 v7 v5
awk
正規表現と一致する場合にのみフィールドを変更する代替コマンド^v[0-9]+$
:
awk '{ for (i=1; i<=NF; ++i) if ($i ~ "^v[0-9]+$") $i = (seen[$i] ? seen[$i] : seen[$i] = "v" ++n) }; 1'
または、読みやすくするために複数行で書式設定します。
awk '
{
for (i=1; i<=NF; ++i)
if ($i ~ "^v[0-9]+$")
$i = (seen[$i] ? seen[$i] : seen[$i] = "v" ++n)
}; 1'
答え2
そしてperl
:
$ echo 'v100 v201 v102 v300 v301 v500 v999 v301' |
perl -pe 's{v\K\d+}{$seen{$&} //= ++$n}ge'
v1 v2 v3 v4 v5 v6 v7 v5
v\d+
一致v
の後に1つ以上の10進数が続きます。その後、一致する部分の開始を\K
リセットし、一連の数字のみが置き換えられるように内容を左に置きます。v
K
v
s
- この
e
フラグを使用すると、置換は次のように処理されます。パスワード評価してe
代替案を作成してください。このコードには$&
一致する部分が含まれています。 A // B
形式であるまたはA
ifが他にA
定義されている場合に拡張されます(ifが次に拡張されるのとはB
反対)。A || B
A
A
本物値などB
)。//=
対応する割り当てフォームです。A //= B
の略語も同じだif (defined(A)) {A} else {A = B}
。
$seen
ハッシュテーブルのインデックスは次のとおりです。ひもこの数値などの値は、v2 v02 v002
異なる文字列である、およびを取得します。上記の例に代わって、数値(010は8進数8ではなく10として扱われます)を正規化できます。あるいは、先行sを維持し、結果を得ることができます。v1 v2 v3
2
02
002
$&
0+$&
v1 v1 v1
s{v0*\K\d+}{$seen{$&} //= ++$n}ge
0
v1 v01 v001
v1
たとえば、見つかった内容を置き換えたくない場合は、rev1sion
次のように追加できます。単語b
の境界\bv\K\d+\b
両方と一致する正規表現演算子()。または、スペースで区切られた単語を置き換え(v1.2
例:単独で残す)など、いくつか追加します。否定的な視線白以外のS
速度の場合:(?<!\S)v\K\d+(?!\S)
。
答え3
GNU実装はこれを正規表現として定義し、特殊変数に一致を書き込むことをawk
サポートします。したがって、これを使用して次のことができます。RS
RT
$ echo 'v100 v201 v102 v300 v301 v500 v999 v301' |
gawk -v RS='v[0-9]+' -v ORS= '
RT {$0 = $0 "v" (RT in seen ? seen[RT] : seen[RT] = ++n)}1'
v1 v2 v3 v4 v5 v6 v7 v5
これはv
数字の後に続くすべての項目に代わるものであり、rev1.2
単語(inまたはなど)内の偶数の数字も置き換えますrev0lution
。絵私のPerlメソッド、数字がゼロで埋められている場合は、調整する必要があります。
答え4
GNU awkのみ:
echo 'v100 v201 v102 v300 v301 v500 v999 v301' |
awk -v RS='[[:space:]]' -F '' '
$0 {printf "%s", $1 (A[$0]?A[$0]:A[$0]=++i) RT}'
v1 v2 v3 v4 v5 v6 v7 v5