참고: 이미 비슷한 질문을 했습니다.AWK: 소스 용어 뒤에 대상 단어를 삽입하는 빠른 방법그리고 저는 AWK의 초급 수준입니다.
이 문제는 무작위로 선택된 여러 행에서 소스 용어 뒤에 여러 대상 용어를 삽입하는 것을 고려합니다.
이 AWK 코드 조각을 사용하면
awk '(NR==FNR){a[$1];next}
FNR in a { gsub(/\<source term\>/,"& target term") }
1
' <(shuf -n 5 -i 1-$(wc -l < file)) file
5개의 임의 행 target term
뒤에 하나를 삽입하고 싶습니다.source term
file
예: dict
왼쪽에 소스 용어가 포함되어 있고 오른쪽에 대상 용어가 포함된 이중 언어 사전이 있습니다.
apple : Apfel
banana : Banane
raspberry : Himbeere
광산은 file
다음 줄로 구성됩니다.
I love the Raspberry Pi.
The monkey loves eating a banana.
Who wants an apple pi?
Apple pen... pineapple pen... pen-pineapple-apple-pen!
The banana is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry or strawberry?
첫 번째 단어 apple
에 대해 임의의 행 1, 3, 5, 4, 7이 선택되었다고 가정해 보겠습니다. apple이라는 단어가 포함된 출력은 다음과 같습니다.
I love the Raspberry Pi.
The monkey loves eating a banana.
Who wants an apple Apfel pi?
Apple Apfel pen... pineapple pen... pen-pineapple-apple-pen!
The banana is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry or strawberry?
banana
그런 다음 선택될 단어 에 대해 5개의 임의의 라인이 추가됩니다 .
I love the Raspberry Pi .
The monkey loves eating a banana .
Who wants an apple Apfel pi ?
Apple Apfel pen... pineapple pen... pen-pineapple-apple-pen!
The banana Banane is tasty and healthy .
An apple a day keeps the doctor away .
Which fruit is tastes better: raspberry or strawberry?
dict
다른 모든 항목은 마지막 항목이 일치할 때까지 계속됩니다 .
무작위로 5개 라인을 선택하고 싶습니다. 줄에 완전한 소스 용어가 있는 경우 전체 단어 apple
만 일치시키려고 합니다 ("pineapple"과 같은 용어는 무시됩니다). 예를 들어 한 줄에 소스 용어가 두 번 포함되어 있으면 그 뒤에도 대상 용어를 삽입하고 싶습니다. 일치 항목은 대소문자를 구분해야 하므로 및 같은 소스 용어도 일치시킬 수 있습니다 .Apfel
apple
apple
apple
Apple
dict
내 질문: 사전을 사용할 수 있고 사전을 선택할 수 있도록 위의 코드 조각을 어떻게 다시 작성합니까?무작위의행을 클릭 file
하고 소스 용어 뒤에 대상 용어를 삽입하시겠습니까?
답변1
다음은 awk를 사용하여 입력 파일에서 5개의 줄 번호를 무작위로 선택하는 방법입니다(첫 번째 패스에서 wc를 사용하면 줄 번호만 계산됩니다).
$ awk -v numLines="$(wc -l < file)" 'BEGIN{srand(); for (i=1; i<=5; i++) print int(1+rand()*numLines)}'
7
2
88
13
18
이제 가져가기만 하면 된다내 이전 답변블록에서 읽은 각 "이전" 문자열에 대해 ARGIND==1
위에 표시된 대로 5개의 줄 번호를 생성하고 배열을 채우고 생성된 줄 번호를 각 줄 번호와 관련된 이전 문자열에 매핑한 다음 파일을 읽습니다. 마지막으로 파일이 입력되면 확인합니다. 줄 번호가 현재 배열에 있고 그렇다면 해당 줄 번호에 대해 배열에 저장된 "이전"을 반복하여 gsub()
이전 답변에서 보여준 작업을 수행합니다.
ARGIND
, IGNORECASE
, 단어 경계, 배열의 배열 및 : 의 \s
약어를 나타내려면 GNU awk를 사용하십시오.[[:space:]]
$ cat tst.sh
#!/usr/bin/env bash
awk -v numLines=$(wc -l < file) '
BEGIN {
FS = "\\s*:\\s*"
IGNORECASE = 1
srand()
}
ARGIND == 1 {
old = "\\<" $1 "\\>"
new = "& " $2
for (i=1; i<=5; i++) {
lineNr = int(1+rand()*numLines)
map[lineNr][old] = new
}
next
}
FNR in map {
for ( old in map[FNR] ) {
new = map[FNR][old]
gsub(old,new)
}
}
{ print }
' dict file
$ ./tst.sh
I love the Raspberry Pi.
The monkey loves eating a banana Banane.
Who wants an apple Apfel pi?
Apple Apfel pen... pineapple pen... pen-pineapple-apple Apfel-pen!
The banana Banane is tasty and healthy.
An apple a day keeps the doctor away.
Which fruit is tastes better: raspberry Himbeere or strawberry?
답변2
확장 정규식 모드(-E) 및 s/// 명령의 (/e) 수정자를 사용하는 GNU sed:
n=$(< file wc -l)
sed -E '/\n/ba
s#^(\S+)\s*:\s*(\S+)$#s/\\<\1\\>/\& \2/Ig#;h'"
s/.*/shuf -n 5 -i '1-$n'/e;G
:a
s/^([0-9]+)(\n.*\n(.*))/\1 \3\2/
/\n.*\n/!s/\n/ /
P;D
" dict | sed -f /dev/stdin file
- 덕트 파일의 내용에서 GNU sed 명령을 생성합니다.
- 명령을 보류 상태로 저장합니다.
- 주사위를 굴려 입력 파일의 줄 길이 내에서 5개의 난수를 생성합니다.
- 보존 모드를 고수하고 이러한 특정 라인에서만 실행되는 sed 명령을 생성하십시오.
- 입력 파일에 생성된 다음 명령을 적용합니다.