우분투에서 명명된 파이프를 시험해 보고 있는데 이전에 사용해 본 경험이 없습니다. 나는 다음을 수행했습니다.
mkfifo pipe
ls>pipe&
cat pipe
그러면 내 폴더에 있는 모든 파일의 목록이 pipe
표시됩니다. 한 번에 파이프 2줄을 읽으려고 합니다. 그래서 한 번 실행하면 폴더의 첫 번째 파일과 두 번째 파일의 이름을 제공하는 명령을 원합니다. 명령을 다시 실행하면 세 번째와 네 번째 파일 이름이 필요합니다. 이를 수행할 수 있는 방법이 있습니까?
나는 노력했다 head -2 pipe
. 처음 두 개의 파일 이름이 표시됩니다. 하지만 다시 실행하면 멈춥니다. 앞으로 나아갈 올바른 방법은 무엇입니까?
답변1
읽기 측에서 FIFO를 열어두기를 원합니다. 한 가지 방법은 bash가 열린 파일 설명자를 유지하도록 하는 것입니다.
#!/bin/bash
mkfifo pipe
ls > pipe &
exec 8< pipe
r2(){
read -ru 8 fn1
read -ru 8 fn2
echo "$fn1" "$fn2"
}
r2 # print out first 2 files
sleep 1 # do something
r2 # print out next 2 files.
답변2
두 줄만 읽고 더 이상 읽지 않는 명령이 필요합니다.
입력이 파이프가 아닐 때 이를 수행하는 기능탐색 가능한, 명령에는 세 가지 옵션이 있습니다.
- 두 번째 개행 문자를 찾을 때까지 한 번에 한 바이트씩 읽습니다.
- 파이프의 내용을 (사용하지 않고) 보고 두 번째 개행 문자가 어디에 있는지 확인한 다음 한 번에 최대한 많은 데이터를 읽습니다.
- 블록의 입력을 읽으십시오. 그러나 두 줄 이상을 읽었다면 초과분을 파이프에 다시 넣으십시오.
read()
1은 바이트당 하나의 시스템 호출만 있기 때문에 많은 시스템에서 비용이 많이 듭니다 . 2와 3은 모든 시스템에서 파이프를 조사하거나 파이프에 데이터를 다시 넣는 것을 지원하지 않기 때문에 모든 시스템에서 작동하지 않으며 여러 프로세스가 동시에 파이프에서 읽을 때 신뢰할 수 없습니다.
따라서 일반적으로 말해서 몇 가지 예외를 제외하면 명령은 읽기에 방해가 되지 않습니다.정확히입력 내용을 검색할 수 없으면 줄 수를 알려줍니다.
대부분의 구현에서는 입력의 처음 두 줄을 head
출력 하지만 더 많은 입력을 소비할 수 있습니다. head -n2
주목할만한 예외 중 하나는 head
ksh93 쉘의 내장 함수로, 가능한지 확인하고 한 번에 한 바이트씩 읽는 기능입니다.
일부 명령은 처리하라는 마지막 줄 이상을 읽지 않도록 지시할 수 있습니다.
GNU의 경우 sed
옵션은 다음과 같습니다 -u
.
sed -u 2q
2줄(한 번에 1바이트)을 읽으면 그게 전부입니다.
이 line
유틸리티(더 이상 표준 유틸리티가 아니므로 지금은 항상 찾을 수 없음)는 한 줄만 읽는 유틸리티입니다.
내장 기능은 한 줄 이상을 읽을 read
수 없습니다 . sh
따라서 line
위의 명령은 다음과 같은 방법으로 구현할 수 있습니다.
IFS= read -r line; printf '%s\n' "$line"
(입력 줄이 끝나지 않더라도 줄 바꿈을 추가한다는 점에 유의하세요).
(POSIX는 line
에 의해 달성될 수 있기 때문에 실제로 삭제를 정당화합니다 read
).
line
추가 개행을 추가하지 않고 eof에서 false를 반환하는 구현의 경우 .
line() {
if IFS= read -r line; then
printf '%s\n' "$line"
else
printf %s "$line"
false
fi
}
그리고 twolines
그냥:
twolines() { line && line; }
그러면 다음과 같이 할 수 있습니다:
mkfifo pipe
ls > pipe &
while
echo next two lines:
twolines
do
continue
done < pipe