동일한 입력 파일에 여러 패스를 만들려면 다음과 같은 간단한 사례가 잘 작동합니다.
$ awk 'p==1{print $1}; p==2{print $2}; p==3{print $3}' p=1 infile p=2 infile p=3 infile
그런데 이 변화가 실패했나요?
$ awk 'p==1{/Jan/ {print $1}}; p==2{print $2}; p==3{print $3}' p=1 infile p=2 infile p=3 infile
나는 다음과 같은 용어를 사용하고 싶지 않습니다.
p==1 && /Jan/ {print $1}
(원본) 코드의 읽기 쉬운 구조를 유지하고 싶기 때문입니다.
각 괄호 안에 조건부 용어를 사용하는 방법은 무엇입니까?
예:
$ cat infile
James Exeter 48
Alex Leeds 22
Jan London 35
원하는 결과:
Jan
Exeter
Leeds
London
48
22
35
답변1
이 연산자는 정규식과 일치하면 1을 반환하고 그렇지 않으면 0을 반환하는 연산자 /regexp/
입니다 .$0
print /foo/ + /bar/
예를 들어, or의 일부로 사용할 수 있지만 if (/foo/) print "match"
in의 일부로 사용하는 것은 유효하지 않은 구문이며, 같은 방식으로 또는 유효하지 않습니다.CONDITION
CONDITION { ACTION }
ACTION
/foo/ {something}
a == b {something}
"whatever" {something}
당신이 원하는 것:
awk '
p==1 {
if (/Jan/) print $1
next
}
p==2 {print $2; next}
p==3 {print $3; next}
' p=1 infile p=2 infile p=3 infile
next
또한 테스트 p==2
와 일치하는 호출을 피 p==3
하도록 주의하세요 p==1
.
여기서도 다음을 수행할 수 있습니다.
awk '{print $p}' p=1 infile p=2 infile p=3 infile
또는 다음과 일치하는 /Jan/
레코드 만 인쇄합니다 p==1
.
awk 'p != 1 || /Jan/ {print $p}' p=1 infile p=2 infile p=3 infile
$
은 또한 연산자이므로 $p
or $ p
또는 $ (p * 2 - p)
or 을 사용할 수 있으며 $ (field_to_print = p)
둘 다 $
연산자를 호출하여 pth 필드 로 확장합니다 .
awk
(라고도 함)의 GNU 구현을 사용하면 직접 설정할 필요 없이 각 인수에 대해 증가하는 것을 gawk
사용할 수 있습니다 .ARGIND
p
gawk 'ARGIND != 1 || /Jan/ {print $ARGIND}' infile infile infile
¹ 또는 p == 0인 경우 전체 레코드
답변2
@StéphaneChazelas 귀하의 특정 질문에 답변했습니다.하지만 분명히 하자면, 원하는 작업을 수행하기 위해 입력 파일에 여러 번 패스할 필요가 없으며 다음과 같이 한 번만 패스하면 됩니다.
$ awk '/Jan/{print $1} {a=a $2 ORS; b=b $3 ORS} END{printf "%s%s", a, b}' infile
Jan
Exeter
Leeds
London
48
22
35
또는 더 일반적으로 여러 필드에 대해 다음을 수행합니다.
$ awk '/Jan/{print $1} {for (i=2; i<=NF; i++) a[i]=a[i] $i ORS} END{for (i=2; i<=NF; i++) printf "%s", a[i]}' infile
Jan
Exeter
Leeds
London
48
22
35
입력 파일이 너무 커서 메모리에 맞지 않는 경우에만 실패합니다.