중괄호 내의 조건

중괄호 내의 조건

동일한 입력 파일에 여러 패스를 만들려면 다음과 같은 간단한 사례가 잘 작동합니다.

$ 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의 일부로 사용하는 것은 유효하지 않은 구문이며, 같은 방식으로 또는 유효하지 않습니다.CONDITIONCONDITION { 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

$은 또한 연산자이므로 $por $ p또는 $ (p * 2 - p)or 을 사용할 수 있으며 $ (field_to_print = p)둘 다 $연산자를 호출하여 pth 필드 로 확장합니다 .

awk(라고도 함)의 GNU 구현을 사용하면 직접 설정할 필요 없이 각 인수에 대해 증가하는 것을 gawk사용할 수 있습니다 .ARGINDp

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

입력 파일이 너무 커서 메모리에 맞지 않는 경우에만 실패합니다.

관련 정보