파이프를 통해 대화식으로 awk 사용

파이프를 통해 대화식으로 awk 사용

보고 있다이 문제awk, 파일이 표준 입력으로 파이프되면 사용자 입력을 읽을 수 없지만 명령줄 인수로 제공된 파일에서 입력을 읽으면 예상대로 작동한다는 것을 확인했습니다 .

예를 들어 스크립트에 다음 BEGIN 블록이 있는 경우 awk:

BEGIN {
    printf "Enter input: "
    getline var < "-"
}

이렇게 실행하면 awk -f ./script.awk file.txt사용자에게 입력하라는 메시지가 표시되고 처리가 계속됩니다 file.txt. 그러나 이렇게 실행하면 cat file.txt | awk -f ./script.awkawk가 파이프에서 가져온 내용을 사용자 입력으로 해석할 것이라고 생각됩니다(따라서 첫 번째 행이 getline채워집니다 ).varfile.txt

awk파일에서 읽는 것처럼 동작하지만 파이프에서 사용하는 방법이 있습니까 ?

물론 임시 파일을 사용할 수도 있지만 이는 우아함과는 거리가 멀습니다.

답변1

프로세스 대체는 간단한 경우에 작동할 수 있지만 파이프된 데이터를 처리하는 동안 콘솔 사용자와 대화할 수 있는 일반적인 접근 방식은 다음과 같습니다.

BEGIN {
    printf "Enter input: " > "/dev/tty"
    getline var < "/dev/tty"
    print var
}

답변2

임시 파일 외에도 프로세스 교체를 위한 셸의 지원을 사용할 수도 있습니다(이는 bash, zsh또는 일부 구현 ksh(이 기능은 ksh88에서 도입됨)을 가정함).

awk -f ./script.awk <(cat file.txt)

이는 읽을 때 첨부된 명령의 출력을 포함하는 구문 awk대신 파일 이름을 제공합니다 .<(...)

답변3

이것이 귀하의 작업 흐름에 적합하다면 awk 자체가 파이프를 열도록 할 수 있습니다. Elements로는 이 작업을 수행할 수 없으므로 ARGV파이프에서 읽은 줄에서 awk의 자동 반복을 얻을 수 없습니다. 대신 awk는 명령줄 인수로 전달된 파일에서 읽거나 파일 인수가 없는 경우 표준 입력에서 읽습니다.

{
    printf "Enter input: "
    getline var
    while (("cat file.txt" | getline) > 0) { … }
}

이 구조는 여러분의 장난감 예제에 맞지 않지만 실제 문제에 맞을 수 있기 때문에 언급하겠습니다.

답변4

시스템이 /dev/fd/[num]연결을 지원하거나 awkGNU인 경우 awk다음에서 작동합니다 awk -f ./script.awk file.txt.

{ some_cmd | 3<&0 <&4 4<&- awk -f ./script.awk /dev/fd/3; } 4<&0

관련 정보