우분투의 명명된 파이프에서 한 번에 n 줄 읽기

우분투의 명명된 파이프에서 한 번에 n 줄 읽기

우분투에서 명명된 파이프를 시험해 보고 있는데 이전에 사용해 본 경험이 없습니다. 나는 다음을 수행했습니다.

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

두 줄만 읽고 더 이상 읽지 않는 명령이 필요합니다.

입력이 파이프가 아닐 때 이를 수행하는 기능탐색 가능한, 명령에는 세 가지 옵션이 있습니다.

  1. 두 번째 개행 문자를 찾을 때까지 한 번에 한 바이트씩 읽습니다.
  2. 파이프의 내용을 (사용하지 않고) 보고 두 번째 개행 문자가 어디에 있는지 확인한 다음 한 번에 최대한 많은 데이터를 읽습니다.
  3. 블록의 입력을 읽으십시오. 그러나 두 줄 이상을 읽었다면 초과분을 파이프에 다시 넣으십시오.

read()1은 바이트당 하나의 시스템 호출만 있기 때문에 많은 시스템에서 비용이 많이 듭니다 . 2와 3은 모든 시스템에서 파이프를 조사하거나 파이프에 데이터를 다시 넣는 것을 지원하지 않기 때문에 모든 시스템에서 작동하지 않으며 여러 프로세스가 동시에 파이프에서 읽을 때 신뢰할 수 없습니다.

따라서 일반적으로 말해서 몇 가지 예외를 제외하면 명령은 읽기에 방해가 되지 않습니다.정확히입력 내용을 검색할 수 없으면 줄 수를 알려줍니다.

대부분의 구현에서는 입력의 처음 두 줄을 head출력 하지만 더 많은 입력을 소비할 수 있습니다. head -n2주목할만한 예외 중 하나는 headksh93 쉘의 내장 함수로, 가능한지 확인하고 한 번에 한 바이트씩 읽는 기능입니다.

일부 명령은 처리하라는 마지막 줄 이상을 읽지 않도록 지시할 수 있습니다.

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

관련 정보