awk에서 변경할 필드 구분 기호가 '\t'인 경우 -F 플래그를 사용하면 작동하지만 FS 변수를 사용하여 필드 구분 기호를 명시적으로 변경하면 작동하지 않는 이유는 무엇입니까?

awk에서 변경할 필드 구분 기호가 '\t'인 경우 -F 플래그를 사용하면 작동하지만 FS 변수를 사용하여 필드 구분 기호를 명시적으로 변경하면 작동하지 않는 이유는 무엇입니까?

Unix 도구를 사용해 볼 때, 설명할 수 없는 미묘함을 만났습니다. 이것이 내가 사용하는 파일이라고 가정 해 봅시다file.txt

Carl Gauss      1       Germany
Isaac Newton    2       England
Leonhard Euler  3       Switzerland
Donald Knuth    4       America
Alan Turing     5       England
Albert Einstein 6       Germany

열은 탭으로 구분됩니다. 이제 각 행의 첫 번째 필드를 추출하려고 한다고 가정해 보겠습니다. 이를 달성하기 위한 두 가지 방법은 다음과 같습니다.

테스트 1:

#!/bin/bash

awk -F'\t' '
{print $1;}
' file.txt

예상대로 출력은 다음과 같습니다.

Carl Gauss
Isaac Newton
Leonhard Euler
Donald Knuth
Alan Turing
Albert Einstein

이제 나는 이 문제를 해결하기 위해 동등한 또 다른 방법을 시도했습니다.

테스트 2:

#!/bin/bash

awk '
BEGIN {
        FS='\t';
}
{print $1;}
' file.txt

이 경우 내가 얻는 결과는 다음과 같습니다.

C
I
L
D
A
A

줄의 첫 글자만 인쇄됩니다. 내가 아는 한, 이 두 가지 방법은 동일해야 하지만 서로 다른 결과를 생성합니다. 또한 다른 방식으로 생성된 다른 파일로 시도해 보았지만 file.txt매번 동일한 결과를 얻었습니다.

이에 대한 설명은 무엇입니까?

답변1

  1. Bourne과 같은 쉘 '에서는 이 작업을 수행할 수 없습니다 (예: .'bash
  2. awk 스크립트 내의 문자열 구분 기호는 ", is 가 아닙니다 '.

FS='\t'으로 바꾸시면 됩니다 FS="\t".

현재 코드는 awk 스크립트에서 분리된 FS=다음 쉘 스크립트에서 독립적으로 실행되고 \t나중에 awk 스크립트에 다시 입력됩니다.

'BEGIN{     FS='\t              ' }             '
^shell ends    ^awk ends        ^shell ends     ^awk ends
 awk begins     shell begins     awk begins      shell begins
                 

이는 \tawk를 호출하기 전에 쉘에 의해 완전히 해석되며 쉘에서 인용되지 않은 문자열은 \t해당 컨텍스트의 쉘에서 이미 리터럴인 것과 동일하므로 t다음과 같이 작성하십시오.t

awk 'BEGIN{ FS='\t' }'

쓰기와 동일:

awk 'BEGIN{ FS='t' }'

이는 다음과 같이 작성하는 것과 동일합니다.

awk 'BEGIN{ FS=t }'

해당 스크립트에서 awk는 t이를 초기화되지 않은 변수로 처리하므로 (필드 분할 목적의 경우) 다음과 같이 작성하는 것과 같습니다.

awk 'BEGIN{ FS="" }'

이는 정의되지 않은 동작입니다(다른 awk 변형에서 다른 작업을 수행함).

쉘에서 awk를 호출하는 대신 shebang을 사용하여 awk를 호출하라는 답변 및/또는 설명을 얻을 수 있지만 그렇게 하지 마십시오.https://stackoverflow.com/a/61002754/1745001왜.

관련 정보