異なるファイル内の同じ行にある複数の文字列パターンを、文字列と一致する番号で置き換えるためのawkスクリプト
Nov 26 2020
<>内の文字列を検索するawkスクリプトが必要です。文字列が見つからない場合は、インデックスカウンターの現在の値(最初は0)に置き換えて、カウンターをインクリメントする必要があります。<>内にすでに認識されている文字列が見つかった場合は、文字列のインデックスを検索して、そのインデックスに置き換える必要があります。これは複数のファイルにわたって実行する必要があります。つまり、プログラムの起動時にのみ、複数のファイルでパターンが検索されてもカウンターはリセットされません。例:file_a.txt:
123abc<abc>xyz
efg
<b>ah
a<c>, <abc>
<c>b
(<abc>, <b>)
file_b.txt:
xyz(<c>, <b>)
xyz<b>xy<abc>z
になるはずです
file_a_new.txt:
123abc<0>xyz
efg
<1>ah
a<2>, <0>
<2>b
(<0>, <1>)
file_b_new.txt:
xyz(<2>, <1>)
xyz<1>xy<0>z
私がこれまでに得たもの:
awk 'match($0, /<[^>]+>/) { k = substr($0, RSTART, RLENGTH)
if (!(k in freq))
freq[k] = n++
$0 = substr($0, 1, RSTART-1) freq[k] substr($0, RSTART+RLENGTH) } { print $0 > (FILENAME ".tmp")
}' files
ただし、これは1行に1つの<>パターンしか検出できませんが、1行に複数の<>パターンが存在する可能性があります。では、どのようにコードを変更する必要がありますか?
編集:ファイルはeditetではなく、新しいファイルを作成する必要があります
回答
3 anubhava Nov 26 2020 at 17:31
文字列として使用gnu-awk
すると、次のように簡単に使用できます。RS
<key>
awk -v RS='<[^>]+>' '{ ORS="" } # init ORS to ""
RT { # when RT is set
if (!(RT in freq)) # if RT is not in freq array
freq[RT] = n++ # save n in freq & increment n
ORS="<" freq[RT] ">" # set ORS to < + n + >
}
{
print $0 > ("/tmp/" FILENAME)
}' file_{a,b}.txt
1 EdMorton Nov 26 2020 at 17:24
awkの使用:
$ cat tst.awk FNR == 1 { close(out) out = FILENAME ".tmp" } { head = "" tail = $0
while ( match(tail,/<[^>]+>/) ) {
tgt = substr(tail,RSTART+1,RLENGTH-2)
if ( !(tgt in map) ) {
map[tgt] = cnt++
}
head = head substr(tail,1,RSTART) map[tgt]
tail = substr(tail,RSTART+RLENGTH-1)
}
print head tail > out
}
$ head file_*.tmp
==> file_a.txt.tmp <==
123abc<0>xyz
efg
<1>ah
a<2>, <0>
<2>b
(<0>, <1>)
==> file_b.txt.tmp <==
xyz(<2>, <1>)
xyz<1>xy<0>z