![이 명령줄에서 <(echo)를 어떻게 이해하나요?](https://linux55.com/image/191362/%EC%9D%B4%20%EB%AA%85%EB%A0%B9%EC%A4%84%EC%97%90%EC%84%9C%20%26lt%3B(echo)%EB%A5%BC%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%EC%9D%B4%ED%95%B4%ED%95%98%EB%82%98%EC%9A%94%3F.png)
이 행은 첫 번째 열을 기준으로 파일을 축소합니다.
awk '{if($1==x){i=i" "$2}else{if(NR>1){print i};i=$0};x=$1;y=$2}' test.cov <(echo)
입력하다:
1001 hisk01
1001 hisk02
1001 hisk03
1002 hisk04
1002 hisk05
1002 hisk06
1003 hisk07
1003 hisk08
산출:
1001 hisk01 hisk02 hisk03
1002 hisk04 hisk05 hisk06
1003 hisk07 hisk08
<(echo)
작동하지만 여기서는 어떻게 작동하는지 모르겠습니다 . 누구든지 나를 도와줄 수 있나요?
감사해요
답변1
<(
GNU Bourne-Again Shell(Bash)의 기능인 "프로세스 교체"입니다. POSIX에는 없습니다.
프로세스 대체는 명령줄 인수로 확장되는 구문입니다. 대상 프로그램은 매개변수를 파일 이름인 것처럼 열 수 있습니다. 결과 파일 설명자는 괄호 사이의 구문에 표시된 명령 파이프라인에 연결됩니다.
즉, <(echo)
와 같은 단어로 확장됩니다 /magic/path/53
. 프로그램이 이 경로를 수신하고 입력용 파일로 열면 에서 읽는 파이프 설명자를 얻습니다 echo
.
echo
효과 는 무엇입니까 ? 빈 줄이 생성됩니다.
유일한 차이점은
some-command <(echo)
그리고
some-command /dev/null
<(echo)
빈 줄만 생성되고 아무것도 생성되지 /dev/null
않습니다.
빈 줄이 포함된 파일의 경로 이름이라고 가정할 수 있습니다 <(echo)
(경로 이름이 출력이 아닌 입력용으로만 열리는 경우).
여기서의 아이디어는 입력에 awk
종료 빈 줄이 포함되어 있는지 확인하는 것 같습니다. 즉, 입력 파일에 무엇이 있든 관계없이 test.cov
추가 빈 줄이 있을 것입니다. 연속된 줄 사이의 상태를 유지하기 때문에 스크립트의 논리에 필요합니다. i
내용이 이전 줄에 따라 달라지고 다음 줄이 도착할 때 인쇄되는 변수가 있습니다 . 마지막 줄에 대해 계산된 내용은 i
인쇄되지 않으므로 의 추가 빈 줄 없이는 마지막 줄이 완전히 처리되지 않습니다 <(echo)
.test.cov
test.cov
종료 개행 문자가 누락된 경우 <(echo)
에는 단순히 제공되지 않습니다. awk에 대한 여러 입력 파일은 단순히 함께 연결되어 단일 문자 스트림을 형성하지 않습니다. 개행 문자의 존재 여부에 관계없이 첫 번째 파일 끝에서 레코드가 구분되고 두 번째 파일에 대해 새 레코드가 생성됩니다.
주변 셸에서 프로세스 교체 기능에 대한 종속성을 제거하는 쉬운 방법이 있습니다.
awk '{if($1==x){i=i" "$2}else{if(NR>1){print i};i=$0};x=$1;y=$2}; END {print i}'
그게 다야! END
누적된 레코드를 인쇄하기 위해 블록을 추가합니다 . if는 처리된 레코드가 없어 정의되지 않았음을 의미하며 빈 값을 인쇄하기 때문에 테스트할 i
필요가 없습니다 . 그러나 이 경우 빈 줄이 출력되며 를 사용하면 이를 방지할 수 있습니다 .NR > 1
NR == 0
i
END {if (i) print i}
답변2
i
이렇게 하면 변수에 있는 버퍼의 마지막 내용 만 출력됩니다 . 이렇게 하면 빈 줄이 생성되므로 awk가 해당 빈 줄을 다시 실행하여 i
변수에 버퍼링된 값을 인쇄합니다. 대신 <(echo)
해당 블록을 사용할 수 있습니다 END{ print i }
.
당신은 또한 볼 수 있습니다내 대답입력이 정렬/정렬되지 않은 두 경우 모두 다른 방법으로 이를 수행하려면 어떻게 해야 합니까?
답변3
귀하가 요청한 질문에 대한 답을 얻었지만 참고로 원하는 작업을 수행하는 가장 일반적인 방법 중 하나는 다음과 같습니다.
$ awk -v ORS= '$1!=prev{print rec; ORS=RS; rec=prev=$1} {rec=rec OFS $2} END{print rec}' file
1001 hisk01 hisk02 hisk03
1002 hisk04 hisk05 hisk06
1003 hisk07 hisk08