다음 Perl 스크립트 ( my.pl
)는 명령 행 args의 파일 또는 STDIN에서 읽을 수 있습니다.
while (<>) {
print($_);
}
perl my.pl
STDIN에서 perl my.pl a.txt
읽은 다음에서 읽습니다 a.txt
. 이것은 매우 편리합니다.
Bash에 해당하는 것이 있습니까?
답변
다음 솔루션은 $1
표준 입력에서 첫 번째 매개 변수로 파일 이름으로 스크립트를 호출 한 경우 파일에서 읽습니다 .
while read line
do
echo "$line"
done < "${1:-/dev/stdin}"
대체이 ${1:-...}
소요 $1
그렇지 않으면 자신의 프로세스의 표준 입력의 파일 이름을 사용하는 정의 된 경우.
답변
아마도 가장 간단한 해결책은 병합 리디렉션 연산자로 stdin을 리디렉션하는 것입니다.
#!/bin/bash
less <&0
Stdin은 파일 디스크립터 0입니다. 위의 내용은 bash 스크립트로 파이프 된 입력을 less의 stdin으로 보냅니다.
답변
가장 간단한 방법은 다음과 같습니다.
#!/bin/sh
cat -
용법:
$ echo test | sh my_script.sh
test
변수에 stdin 을 할당하려면 다음을 사용 STDIN=$(cat -)
하거나 단순히 STDIN=$(cat)
연산자가 필요하지 않은 것처럼 ( @ mklement0 comment에 따라 ) 사용할 수 있습니다.
표준 입력 에서 각 줄을 구문 분석하려면 다음 스크립트를 시도하십시오.
#!/bin/bash
while IFS= read -r line; do
printf '%s\n' "$line"
done
파일 또는 stdin 에서 읽으려면 (인수가없는 경우) 다음으로 확장 할 수 있습니다.
#!/bin/bash
file=${1--} # POSIX-compliant; ${1:--} can be used either.
while IFS= read -r line; do
printf '%s\n' "$line" # Or: env POSIXLY_CORRECT=1 echo "$line"
done < <(cat -- "$file")
노트:
—
read -r
백 슬래시 문자를 특별한 방식으로 취급하지 마십시오. 각 백 슬래시를 입력 라인의 일부로 간주하십시오.– 설정하지 않고
IFS
의 기본적으로 시퀀스 Space와 Tab라인의 시작과 끝에서 무시 (트리밍)된다.– 사용
printf
대신에이echo
라인이 단일 구성 할 때 빈 줄을 인쇄 피하기 위해-e
,-n
또는-E
. 그러나env POSIXLY_CORRECT=1 echo "$line"
이를 사용 하여 외부 GNUecho
를 실행 하는 해결 방법이 있습니다. 참조 : 어떻게 “-e”를 에코합니까?
참조 : 인수가 전달되지 않을 때 stdin을 읽는 방법은 무엇입니까? stackoverflow SE에서
답변
나는 이것이 직접적인 방법이라고 생각합니다.
$ cat reader.sh
#!/bin/bash
while read line; do
echo "reading: ${line}"
done < /dev/stdin
–
$ cat writer.sh
#!/bin/bash
for i in {0..5}; do
echo "line ${i}"
done
–
$ ./writer.sh | ./reader.sh
reading: line 0
reading: line 1
reading: line 2
reading: line 3
reading: line 4
reading: line 5
답변
이 echo
솔루션 IFS
은 입력 스트림을 중단 할 때마다 새 줄을 추가 합니다. @fgm의 답변 은 약간 수정 될 수 있습니다 :
cat "${1:-/dev/stdin}" > "${2:-/dev/stdout}"
답변
질문의 Perl 루프 는 명령 행의 모든 파일 이름 인수 또는 파일이 지정되지 않은 경우 표준 입력에서 읽습니다 . 내가 본 답변은 파일이 지정되지 않은 경우 단일 파일 또는 표준 입력을 처리하는 것으로 보입니다.
종종 UUOC ( Unless Use of cat
) 로 정확하게 정의 되기는하지만 cat
작업에 가장 적합한 도구 인 경우 가 종종 있으며 다음 중 하나 일 수 있습니다.
cat "$@" |
while read -r line
do
echo "$line"
done
이것의 유일한 단점은 하위 셸에서 실행되는 파이프 라인을 생성하므로 while
루프의 변수 할당과 같은 항목 은 파이프 라인 외부에서 액세스 할 수 없습니다. 그 bash
방법은 프로세스 대체입니다 .
while read -r line
do
echo "$line"
done < <(cat "$@")
이렇게하면 while
루프가 기본 셸에서 실행되므로 루프에 설정된 변수는 루프 외부에서 액세스 할 수 있습니다.
답변
OP에 주어진 코드를 가진 Perl의 행동은 인수를 전혀 또는 여러 개 취할 수 없으며 인수가 단일 하이픈 인 경우 -
stdin으로 이해됩니다. 또한 파일 이름을 항상로 사용할 수 있습니다 $ARGV
. 지금까지 주어진 답변 중 어느 것도 이러한 점에서 Perl의 행동을 모방하지 않습니다. 순수한 Bash 가능성이 있습니다. 트릭은 exec
적절하게 사용하는 것 입니다.
#!/bin/bash
(($#)) || set -- -
while (($#)); do
{ [[ $1 = - ]] || exec < "$1"; } &&
while read -r; do
printf '%s\n' "$REPLY"
done
shift
done
사용 가능한 파일 이름 $1
.
인수가 제공되지 않으면 인위적 -
으로 첫 번째 위치 매개 변수로 설정 됩니다. 그런 다음 매개 변수를 반복합니다. 매개 변수가 아닌 경우 -
파일 이름에서 표준 입력을로 리디렉션합니다 exec
. 이 리디렉션이 성공하면 루프로 while
루프합니다. 표준 REPLY
변수를 사용하고 있으며이 경우 재설정 할 필요가 없습니다 IFS
. 다른 이름을 원하면 재설정해야합니다 IFS
(물론 원하지 않고 수행중인 작업을 알고 있지 않은 경우).
while IFS= read -r line; do
printf '%s\n' "$line"
done