Bash 재사용 프로세스 대체 파일

Bash 재사용 프로세스 대체 파일

파일을 입력으로 사용하여 다양한 작업을 수행하는 대규모 스크립트가 있습니다. 이것은 테스트 버전입니다:

echo "cat: $1"
cat $1
echo "grep: $1"
grep hello $1
echo "sed: $1"
sed 's/hello/world/g' $1

내 스크립트에서 프로세스 대체를 사용할 수 있기를 원하지만 첫 번째 명령( cat)만 작동하고 나머지는 작동하지 않습니다. 파이프라인이기 때문인 것 같아요.

$ myscript.sh <(echo hello)

다음을 인쇄해야 합니다:

cat: /dev/fd/63
hello
grep: /dev/fd/63
hello
sed: /dev/fd/63
world

가능합니까?

답변1

<(…)구성은 파이프를 생성합니다. 파이프는 유사한 filename 을 통과 /dev/fd/63하지만 이는 특별한 유형의 파일입니다. 실제로 파이프를 여는 것은 파일 설명자 63을 복사하는 것을 의미합니다. (끝 참조이 답변더 많은 설명을 원하시면. )

파이프에서 읽는 것은 파괴적인 작업입니다. 일단 바이트를 캡처하면 다시 되돌릴 수 없습니다. 따라서 스크립트는 파이프의 출력을 저장해야 합니다. 임시 파일(입력이 큰 경우 선호) 또는 변수(입력이 작은 경우 선호)를 사용할 수 있습니다. 임시 파일 사용:

tmp=$(mktemp)
cat <"$1" >"$tmp"
cat <"$tmp"
grep hello <"$tmp"
sed 's/hello/world/g' <"$tmp"
rm -f "$tmp"

(두 호출을 cat로 결합할 수 있습니다 tee <"$1" -- "$tmp".) 변수 사용:

tmp=$(cat)
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'

명령 대체는 $(…)명령 출력 끝에 있는 줄 바꿈을 잘라냅니다. 이를 방지하려면 추가 문자를 추가한 다음 제거하세요.

tmp=$(cat; echo a); tmp=${tmp%a}
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'

그런데,변수 대체에 대한 큰따옴표를 잊지 마십시오.

답변2

파일 작업을 할 때 해당 데이터를 여러 번 읽을 수 있습니다. 명명된 파이프(실제로 프로세스 대체를 통해 생성됨)를 사용하는 경우 한 번만 읽을 수 있습니다. 따라서 grepsed명령은 빈 입력을 받습니다.

(파이프라인을 이해하는 방법잘 읽어보시면 좋을 것 같습니다. )

프로세스 교체를 위해 다음과 같이 작성할 수 있습니다.

cat $1 | tee >(echo "cat: $1"; cat) | tee >(echo "grep: $1"; grep hello) | (echo "sed: $1"; sed 's/hello/world/g')

하지만 이 경우 두 번째 catgrepsed번째는 병렬로 실행되고 출력이 인터리브됩니다. 이것이 더 유용할 수 있습니다:

cat $1 | tee >(cat > cat.txt) | tee >(grep hello > grep.txt) | sed 's/hello/world/g' > sed.txt

답변3

일반적인 접근 방식은 $1매개변수를 선택적으로 만드는 것입니다. 그런 다음 FILE=${1-/dev/stdin}여러 번 정의하고 사용할 수 있습니다 . FILE그러나 파이프에 대한 다중 읽기는 순차적으로 읽혀지며 데이터는 반복되지 않습니다.

이 문제를 해결하는 가장 쉬운 방법은 임시 파일을 사용하는 것입니다.

if [ -z "$1" ] ; then FILE=$(mktemp); cat >FILE; else FILE=$1; fi

일부 파일 이름을 명시적으로(결국) 전달하려면 /dev/fd/x동일한 임시 파일 트릭을 사용할 수 있습니다.

FILE=$(mktemp); cat "$1" >FILE

tee복잡한 방법을 사용하여 stdin 파일 설명자의 입력을 여러 다른 파일 설명자로 복사할 수도 있습니다 . 그러나 결국 이 방법은 매우 번거로울 수 있습니다.

답변4

프로세스 대체를 통해 얻은 I 파일은 기본 구현에 따라 검색할 수 없으므로 여러 번 읽을 수 없습니다.

관련 정보