awk의 print/printf 출력을 쉘 명령으로 파이프하여 해당 명령문이 관련되지 않은 다른 모든 print/printf 명령문 다음에 실행되도록 합니다.

awk의 print/printf 출력을 쉘 명령으로 파이프하여 해당 명령문이 관련되지 않은 다른 모든 print/printf 명령문 다음에 실행되도록 합니다.

awk스크립트가 주어지면:

END  {
print "Y" | "cat" 

print "X"
print "X"
}

# Output: 
# X
# X
# Y

Y는 다른 명령문보다 먼저 실행되어야 하므로 Y를 먼저 인쇄하는 것은 어떨까요?

답변1

cats 이전에 프로세스를 종료하고 Y인쇄 하려면 s 이후에 호출 X하면 됩니다 .close("cat")print "Y" | "cat"

나머지 내용은 맨페이지에 설명되어 있으므로 읽어보는 것이 좋습니다.

Y는 다른 명령문보다 먼저 실행되어야 하므로 Y를 먼저 인쇄하는 것은 어떨까요?

cat해당 출력은 다른 문보다 먼저 작성되거나 종료되어서는 안 됩니다. 호출 전, 호출 후 또는 호출 사이에 출력을 쓸 수 있습니다 print "X".

print ... | "command ..."awk에서 이와 같은 것을 사용 하면 command ..표준 입력이 파이프에 연결된 비동기 프로세스로 시작되며(를 통해 popen("command ...", "w")) 프로세스가 반드시 종료되지 않고 출력을 호출하고 쓰기 전에 close("command ...")(또는 awk가 공식을 종료할 때 암시적으로) 완전한).

다음 예를 참조하세요.

BEGIN {
   print "foo" | "cat > file"
   print "bar" | "cat > file"
}

결과에는 file두 줄이 포함되며, foo명령 barcat > file각 줄에 대해 개별적으로 실행되지 않습니다.

답변2

awk의 리디렉션과 파이프는 sh의 리디렉션과 파이프와 유사하지만 한 가지 큰 차이점이 있습니다. sh에서는 foo >bar명령을 실행하는 동안에만 열린 상태를 유지하고 대기하고 종료합니다. awk에서 리디렉션 또는 파이프는 명시적으로 닫힐 때까지 열린 상태로 유지되며 동일한 파일 이름이나 명령에 대한 여러 리디렉션 또는 파이프는 열린 리디렉션/파이프를 재사용합니다.barfoofoo | barfoobar

예를 들어, sh에서는 각 정렬 명령이 두 줄의 입력만 가져오므로 a, b, c, a가 인쇄됩니다.b

{ echo b; echo a; } | sort
echo c
{ echo b; echo a; } | sort

그러나 awk에서는 , c, a, a, b를 인쇄합니다 b(awk의 출력이 라인 버퍼라고 가정하고 그렇지 않으면 c지연될 수 있음). 명령이 하나뿐이고 sort모든 입력 데이터를 얻을 때까지 아무것도 인쇄되지 않기 때문입니다. 파이프의 입력 측이 닫혀 있을 때만 발생합니다.

{ print "b"; print "a"; } | "sort";
print "c";
{ print "b"; print "a"; } | "sort";

파이프 명령을 종료하려면 close이 함수를 명시적으로 호출하세요. Awk는 종료 시 열려 있는 모든 파이프와 리디렉션을 암시적으로 닫습니다. 그러면 a, b, c, a, 가 인쇄됩니다 b.

{ print "b"; print "a"; } | "sort"; close("sort");
print "c";
{ print "b"; print "a"; } | "sort"; close("sort");

foo다시 말하지만, 이 awk 조각은 첫 번째 줄이 한 번 열리고 두 번째 줄이 실행될 때 열려 있기 때문에 두 줄로 구성된 파일을 생성합니다 .

print "hello" >"foo";
print "world" >"foo";

그리고 이 sh 조각은 두 번째 줄이 첫 번째 줄에서 생성된 파일을 열고 쓰기 전에 잘라내기 때문에 단일 줄 파일을 생성합니다 world.

echo hello >foo
echo world >foo

awk가 이런 방식으로 설계된 주된 이유는 각 처리 라인에 대해 암시적 루프가 있기 때문입니다. sh에서 루프의 줄을 처리하려면 일반적으로 루프 주위에 리디렉션을 작성합니다.

while read line; do
  if condition "$line"; then
    process line
  fi
done >output

하지만 awk에서는 암시적 루프에 리디렉션을 적용할 수 없으므로 다음과 같이 작성합니다.

condition($0) { process $0 >"output" }

awk 방식은 루프나 다른 블록 중간에서도 파이프를 마음대로 열고 닫을 수 있기 때문에 더욱 강력합니다. sh에서는 리디렉션을 위해 내장 명령을 사용할 수 있지만 exec파이프는 사용할 수 없습니다. 파이프는 (복합일 수도 있는) 명령에 전체적으로 적용되어야 합니다.

관련 정보