awk의 코프로세스 및 양방향 파이프

awk의 코프로세스 및 양방향 파이프

command | getline var의 차이점을 이해하려고 노력하고 있습니다 command |& getline var. 보통 어느 것을 사용해야 합니까? 코프로세스와 양방향 파이프에 대해 읽었지만 상황이 정말 혼란스러워지기 때문에 설명이 필요합니다.

사실 제가 사용하고 있는 건

kmd=sprintf("%s%d\n", "tput bold; tput setaf ", knum)
tseq[knam] = ( (kmd | getline outp) > 0 ? outp : "<" knam ">" )
close(kmd)

여기서 공동 프로세스는 무엇입니까? tput을 사용하고 있습니까? 코드에는 단방향 파이프 통신만 있다고 생각합니다. 이를 사용하면 어떤 이점이 kmd |& getline outp있으며 후자를 사용해야 합니까?

답변1

귀하의 질문에 있는 코드에는 보조 프로세스가 없습니다. 호출할 하위 쉘을 생성한 tput다음 를 사용하여 해당 하위 쉘의 출력을 읽는 것뿐입니다 getline.

정보 What would be the benefit of using kmd |& getline outp, and should I use the latter instead?- 아무 소용이 없을 뿐만 아니라 이는 구문의 절반에 불과하므로 다음과 같은 것이 필요합니다(오류 처리 포함).

print knum |& kcmd
kcmd |& getline outp
close(kcmd)

그러나 이는 계속해서 stdin을 읽고 stdout을 생성하는 명령을 포함하는 경우에만 의미가 있습니다. kcmd설사 그렇게 한다고 해도 수행하려는 작업에 아무런 소용이 없으며 코드가 불필요하게 됩니다. 둔한 사람.

다음은 코루틴이 유용한 경우의 예입니다. 파이프를 통해 들어오는 숫자 스트림을 정렬한 sort다음 숫자를 인쇄하기 전에 숫자로 작업을 수행합니다(예: 읽은 줄 수 또는 내용으로 나누기).

$ cat tst.awk
BEGIN {
    cmd = "sort -rn"
}
{ print |& cmd }
END {
    close(cmd, "to")
    while ( (cmd |& getline line) > 0 ) {
        print line, line / NR
    }
    close(cmd)
}

$ seq 5 | awk -f tst.awk
5 1
4 0.8
3 0.6
2 0.4
1 0.2

기본적으로 임시 파일에 써야 하는 awk 스크립트를 작성하는 경우 해당 파일에 대해 외부 명령을 호출한 다음 해당 명령의 출력을 다시 스크립트로 읽어옵니다. 여기서 코프로세싱 사용을 고려해야 합니다. 임시 파일을 만들 필요가 없기 때문에 사실입니다.

자세한 내용은 Arnold Robbins의 Effective AWK 프로그래밍 5판 책을 다운로드하고 다른 프로세스와의 양방향 통신 섹션을 읽어보세요.

답변2

아니요, 계속해서 간단한 "|"를 사용해야 합니다. 귀하의 작업이 다음과 같은 경우: 일부 데이터를 외부 도구에 제공하고 도구에서 제공하는 결과를 사용하십시오. 그러면 간단한 단방향 파이프로 충분합니다.

양방향 파이프는 다음과 같은 경우에만 필요합니다.

  • 자신의 프로세스가 수명을 다하는 동안 외부 도구의 동일한 인스턴스를 메모리에 유지하려고 합니다.
  • 외부 도구로 보내는 데이터는 논리적으로 패킷으로 구분됩니다.
  • 다음 패킷을 보내기 전에 하나의 패킷을 처리한 결과를 받아야 합니다.
  • 이전 패킷의 결과를 기반으로 다음 패킷을 조정해야 합니다.

이 네 가지 질문 중 하나가 "아니요"이면 양방향 파이프가 필요하지 않습니다.

양방향 파이프를 사용하는 실제 사례를 만드는 것은 어렵습니다. 아마도 일부 데이터베이스 쿼리 도구나 웹 애플리케이션과 함께 사용하기 위해 발명되었을 것입니다. 그러나 대부분의 경우 어떤 종류의 서버를 사용해야 하는 경우 이러한 작업은 일반적으로 , 심지어 셸과 같은 언어로 perl해결 될 수 있습니다 python. awk일반적으로 텍스트 처리 전용으로 예약되어 있습니다.

비현실적이지만 기술적으로는 올바른 예는 다음과 같습니다.

#!/bin/gawk
BEGIN {
  tool="bc"

  print "2+3" |& tool
  tool |& getline res

  if (res>4)
     print "5+6" |& tool
  else 
     print "10+45" |& tool
  tool |& getline res

  close(tool, "to")

  print res
}

여기에서 볼 수 있듯이 첫 번째 인쇄에서는 "쿼리"를 외부 도구( bc이 경우 간단한 계산기)로 보냅니다. 그런 다음 첫 번째 쿼리의 결과를 기반으로 다른 쿼리를 보내고 마지막으로 결과를 인쇄합니다. 두 쿼리를 모두 처리하는 도구의 동일한 인스턴스입니다. 처음부터 print "2+3" |& command특별 성명까지 공개됩니다 close(command, "to").

관련 정보