다른 파일의 같은 줄에서 문자열 패턴의 여러 발생을 문자열과 일치하는 숫자로 바꾸는 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
그러나 이것은 한 줄에 하나의 <> 패턴 만 감지 할 수 있지만 한 줄에 여러 <> 패턴이있을 수 있습니다. 그렇다면 코드를 어떻게 변경해야합니까?
편집 : 파일은 편집 할 수 없으며 대신 새 파일을 만들어야합니다.
답변
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