이 awk
스크립트가 주어지면:
END {
print "Y" | "cat"
print "X"
print "X"
}
# Output:
# X
# X
# Y
Y는 다른 명령문보다 먼저 실행되어야 하므로 Y를 먼저 인쇄하는 것은 어떨까요?
답변1
cat
s 이전에 프로세스를 종료하고 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
명령 bar
은 cat > file
각 줄에 대해 개별적으로 실행되지 않습니다.
답변2
awk의 리디렉션과 파이프는 sh의 리디렉션과 파이프와 유사하지만 한 가지 큰 차이점이 있습니다. sh에서는 foo >bar
명령을 실행하는 동안에만 열린 상태를 유지하고 대기하고 종료합니다. awk에서 리디렉션 또는 파이프는 명시적으로 닫힐 때까지 열린 상태로 유지되며 동일한 파일 이름이나 명령에 대한 여러 리디렉션 또는 파이프는 열린 리디렉션/파이프를 재사용합니다.bar
foo
foo | bar
foo
bar
예를 들어, 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
파이프는 사용할 수 없습니다. 파이프는 (복합일 수도 있는) 명령에 전체적으로 적용되어야 합니다.