Bash의 awk 패턴과 일치하는 변수 정의

Bash의 awk 패턴과 일치하는 변수 정의

X는 {0,40,80,...,200}에 있는 "time: X" 텍스트 뒤에 오는 100줄을 가져오려고 합니다. 이것이 내가 지금까지 가지고 있는 것입니다:

#!/bin/bash
start=1
end=5
for i in $(seq $start $end);do 
  j=$(($i*40))
  awk '/time: $j/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-$j.txt
done 

그러나 이것은 작동하지 않는 것 같습니다. 내 질문은 특히 변수 $j에 관한 것이며 '/time: ...' 뒤에 변수를 정의해야 하는 방법에 관한 것입니다.

예를 들어 "file"이라는 파일이 있습니다.

time: 1
1 2 3 
1 33 1 
2 31 4
time: 40
2 1 3 
9 8 77
1 3 4

이 경우에는 두 개의 별도 파일을 만들고 싶습니다.

1 2 3 
1 33 1 
2 31 4

두 번째는 다음과 같습니다.

1 2 3 
1 33 1 
2 31 4

mazs가 언급한 것처럼 $j를 변수로 전달하려고 시도했지만 여전히 빈 파일이 제공됩니다. 내가하는 방법은 다음과 같습니다.

awk -v jj=$j '/time: jj/{for(i=1;i<3;i++){getline;print}}' file > fileX-$j.txt

답변1

두 가지 질문이 있습니다. 첫 번째는 쉘이 $j작은따옴표 내에서 확장되지 않는다는 것입니다. 즉, 변수 값이 아닌 '$j'문자열을 원한다고 쉘에 알립니다 .$jj

이 경우 값에는 숫자만 포함되므로 작은따옴표 밖에 넣을 수 있습니다.

awk '/time: '"$j"'/{for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt

j값에 정규식 특수 문자( .등) 가 포함된 경우 *해당 문자는 그렇게 해석됩니다. 예를 들어

j='2*3'
awk '/foo '"$j"' bar/'

스크립트는 대신 , 등 foo 3 barfoo 23 bar포함 하는 줄을 인쇄합니다 . 값에 awk가 있으면 예를 들어 정규식 일치 구조의 끝이 표시됩니다.foo 223 barfoo 2*3 bar/

j='2/3'
awk '/foo '"$j"' bar/'

토큰 시퀀스 /foo 2/, 3, bar/구문상 올바르지 않다고 awk에서 불평하게 됩니다.

명령줄 옵션을 사용하여 awk에 대한 변수를 정의할 수 있습니다 -v.

j='a\tb'
awk -v j="$j" '{print j}'

이 값 쌍은 백슬래시 확장을 수행합니다 j. 예를 들어 위의 코드 조각은 각 줄을 a↦b문자로 바꿉니다.

그러나 awk는 내부 변수를 확장하지 않기 때문에 이는 귀하의 경우에 직접 적용되지 않습니다 /…/. 이는 변수의 값이 아니라 /foo/string 과 일치합니다 . 정규식 일치에 변수를 사용하려면 다음 함수를 사용해야 합니다 .foofoomatch

awk -v j="$j" 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt

이는 j백슬래시가 포함되지 않은 값에 적용됩니다. 예를 들어 j로 설정 하면 등 a/b*c의 행과 일치합니다. 로 설정 하면 뒤에 공백과 탭이 포함된 행 과 일치합니다 .time: a/ctime: a/bcj\ttime:

쉘 변수의 값을 awk에 전달하려면 값이 무엇이든 환경을 통해 전달하십시오.

export j
awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt

또는 j나머지 스크립트가 진행되는 동안 환경에 갇히지 않으려면 다음을 수행하세요.

j="$j" awk 'match($0, "time: "+j) {for(i=1;i<=100;i++}{getline;print}}' file > fileX-"$j".txt

정규식 대신 리터럴 문자열을 검색하려면 index대신 이 함수를 사용할 수 있습니다 match.

j='a*b'
awk 'index($0, "time: "+j)'

인쇄에는 가 포함되어 있습니다 time: a*b.

답변2

$j 쉘 변수를 awk에 전달해야 합니다:

awk -v jj="$j" '...'

인수에 백슬래시 확장이 적용되므로 변수 값에 백슬래시가 포함되어 있지 않다고 가정합니다 awk -v.

관련 정보