Bash에서 파일 또는 표준 입력에서 읽는 방법
스크립트Perl')my.pl)는 명령줄 인수의 파일 또는 표준 입력(STDIN)에서 읽을 수 있습니다.
while (<>) {
print($_);
}
perl my.pl입력에서 , 는 표준 에서 읽습니다.perl my.pl a.txta.txt이거 정말 편리하네요.
Bash에 동등한 것이 있나요?
하여 스크립트가 되면 다음 .$1표준 입력에서 제외됩니다.
while read line
do
echo "$line"
done < "${1:-/dev/stdin}"
★★★${1:-...}이 걸리다$1츠요시그렇지 않으면 자체 프로세스의 표준 입력 파일 이름이 사용됩니다.
가장 간단한 해결책은 표준 입력을 병합 리다이렉트 연산자로 리다이렉트하는 것입니다.
#!/bin/bash
less <&0
표준 입력은 파일 기술자 0입니다.위의 명령어는 bash 스크립트에 파이프로 연결된 입력을 보다 적은 표준 입력으로 보냅니다.
파일 설명자 리디렉션에 대한 자세한 내용을 읽어 보십시오.
가장 간단한 방법은 다음과 같습니다.
#!/bin/sh
cat -
사용방법:
$ echo test | sh my_script.sh
test
stdin을 변수에 할당하려면 다음을 사용합니다.STDIN=$(cat -) 간단히 ,STDIN=$(cat)as 연산자는 필요 없습니다(@comment0 코멘트에 따름).
표준 입력으로부터 각 행을 해석하려면 , 다음의 스크립트를 실행합니다.
#!/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디폴트로는, 행의 선두와 말미의 및 의 시퀀스는 무시됩니다(비활성화).- ★★★
printfecho이 되어 있는 빈-e,-n★★★★★★★★★★★★★★★★★」-E이렇게 해결env POSIXLY_CORRECT=1 echo "$line"외부 GNU를 실행합니다.echo그걸 뒷받침하는 거죠'-e'를 에코하는 방법'을 참조해 주세요.
참조: 인수가 전달되지 않았을 때 stdin을 읽는 방법스택오버플로우 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(무익한 사용)라고 정확하게 비웃는 경우가 많지만cat음, ),, 다, 다, 다, 다, 다, 다, 다, 다, 다, .cat이며, 중 할 수 .
cat "$@" |
while read -r line
do
echo "$line"
done
입니다. 서브셸에서는 과 같은 이 생성된다는 것입니다.따라서 이 파이프라인이 서브셸의 변수 할당과 같이while파이프라인 외부에서는 루프에 액세스할 수 없습니다.bash프로세스 대체:
while read -r line
do
echo "$line"
done < <(cat "$@")
이 the가 .while루프가 메인셸 내에서 동작하기 때문에 루프 내에 설정된 변수는 루프 외부에서 액세스할 수 있습니다.
또는 할 수 , 하이픈 Perl을 사용할 수 있습니다.-【stdin】【stdin】【stdin】【stdin】파일 ,, 일, 음, 음, 음, 음, 음, 음, 음, 음, 음, 음, 음, 음, ,, ,, ,, ,, ,, ,, ,, ,, ,, moreover, moreover, moreover $ARGV지금까지 나온 답변 중 Perl의 행동을 실제로 모방한 것은 없다.하다요령은 사용법이다.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
더 정확히 말하면...
while IFS= read -r line ; do
printf "%s\n" "$line"
done < file
다음 코드를 사용해 보십시오.
while IFS= read -r line; do
echo "$line"
done < file
이다.sh(Dash on Debian으로 테스트)는 꽤 읽기 쉽지만, 그것은 취향의 문제입니다.
if [ -n "$1" ]; then
cat "$1"
else
cat
fi | commands_and_transformations
않은 , 첫 번째 파라미터는 비어있지 않습니다.cat 않으면 " " " " " " " "cat그러면 전체 출력입니다.if는, 「이렇게 하면 안 된다」에 처리됩니다.commands_and_transformations.
저는 위의 답변을 모두 조합하여 제 요구에 맞는 셸 기능을 만들었습니다.이것은 Windows 10 머신 2대의 Cygwin 단말기에서 가져온 것입니다.그 사이에 공유 폴더가 있습니다.다음 사항을 처리할 수 있어야 합니다.
cat file.cpp | txtx < file.cpptx file.cpp
특정의 파일명이 지정되어 있는 경우는, 카피시에 같은 파일명을 사용할 필요가 있습니다.입력 데이터 스트림이 파이프로 연결된 경우, 시간 분 및 초가 포함된 임시 파일 이름을 생성해야 합니다.공유 기본 폴더에는 요일의 하위 폴더가 있습니다.이것은 조직적인 목적입니다.
보세요, 제 요구에 맞는 궁극적인 스크립트입니다.
tx ()
{
if [ $# -eq 0 ]; then
local TMP=/tmp/tx.$(date +'%H%M%S')
while IFS= read -r line; do
echo "$line"
done < /dev/stdin > $TMP
cp $TMP //$OTHER/stargate/$(date +'%a')/
rm -f $TMP
else
[ -r $1 ] && cp $1 //$OTHER/stargate/$(date +'%a')/ || echo "cannot read file"
fi
}
이것을 더욱 최적화할 수 있는 방법이 있다면 알고 싶습니다.
#!/usr/bin/bash
if [ -p /dev/stdin ]; then
#for FILE in "$@" /dev/stdin
for FILE in /dev/stdin
do
while IFS= read -r LINE
do
echo "$@" "$LINE" #print line argument and stdin
done < "$FILE"
done
else
printf "[ -p /dev/stdin ] is false\n"
#dosomething
fi
실행 중:
echo var var2 | bash std.sh
결과:
var var2
실행 중:
bash std.sh < <(cat /etc/passwd)
결과:
root:x:0:0::/root:/usr/bin/bash
bin:x:1:1::/:/usr/bin/nologin
daemon:x:2:2::/:/usr/bin/nologin
mail:x:8:12::/var/spool/mail:/usr/bin/nologin
두 가지 주요 방법:
- 인수 파일과 stdin을 단일 스트림으로 파이프하여 stdin과 같은 프로세스(스트림접근법)
- 또는 stdin(및 인수 파일)을 명명된 파이프로 리다이렉트하여 파일(파일 접근법)과 같은 프로세스를 수행합니다.
스트림 어프로치
이전 답변에 대한 사소한 수정 사항:
cat아니라, 이에요.less번호부여가 필요 더 빠르고 페이지 매김이 필요 없습니다.$1파일) 첫 번째 인수 파일(존재하는 경우)에서$*이치노 있는 (예: stdincat고 하다)#!/bin/bash cat $* | ...
파일 어프로치
명명된 파이프에 쓰는 것은 좀 더 복잡하지만 stdin(또는 파일)을 단일 파일처럼 처리할 수 있습니다.
「」를 합니다.
mkfifo.기입 프로세스를 병행합니다.지정된 파이프를 읽지 않으면 차단될 수 있습니다.
하려면 (경우 에 따라) stdin을 합니다.
<&0(다른 사람이 코멘트하고 있는 것과 달리, 이것은 여기서 선택사항이 아닙니다).#!/bin/bash mkfifo /tmp/myStream cat $* <&0 > /tmp/myStream & # separate subprocess (!) AddYourCommandHere /tmp/myStream # process input like a file, rm /tmp/myStream # cleaning up
파일 접근법: 다양성
인수를 지정하지 않은 경우에만 명명된 파이프를 생성하십시오.명명된 파이프가 차단될 수 있으므로 파일에서 읽을 때 더 안정적일 수 있습니다.
#!/bin/bash
FILES=$*
if echo $FILES | egrep -v . >&/dev/null; then # if $FILES is empty
mkfifo /tmp/myStream
cat <&0 > /tmp/myStream &
FILES=/tmp/myStream
fi
AddYourCommandHere $FILES # do something ;)
if [ -e /tmp/myStream ]; then
rm /tmp/myStream
fi
또한 모든 것을 단일 스트림에 연결하는 대신 파일 및 stdin을 반복할 수 있습니다.
for file in $FILES; do
AddYourCommandHere $file
done
★★${1:-/dev/stdin} 첫 인수는 할 수 .
ARGS='$*'
if [ -z "$*" ]; then
ARGS='-'
fi
eval "cat -- $ARGS" | while read line
do
echo "$line"
done
stdin에서 변수로 읽거나 파일에서 변수로 읽습니다.
기존 응답의 대부분의 예에서는 stdin에서 읽으면 각 행을 즉시 에코하는 루프가 사용됩니다.이건 네가 정말 하고 싶은 일이 아닐 수도 있어.
대부분의 경우 file 인수만 받아들이는 명령을 호출하는 스크립트를 작성해야 합니다.그러나 스크립트에서는 stdin을 지원하는 것이 좋습니다.이 경우 먼저 full stdin을 읽은 후 파일로 제공해야 합니다.
예를 들어보자.다음 스크립트는 파일 또는 stdin을 통해 전달된 증명서(PEM 형식)의 증명서 세부사항을 인쇄합니다.
# print-cert script
content=""
while read line
do
content="$content$line\n"
done < "${1:-/dev/stdin}"
# Remove the last newline appended in the above loop
content=${content%\\n}
# Keytool accepts certificate only via a file, but in our script we fix this.
keytool -printcert -v -file <(echo -e $content)
# Read from file
cert-print mycert.crt
# Owner: CN=....
# Issuer: ....
# ....
# Or read from stdin (by pasting)
cert-print
#..paste the cert here and press enter
# Ctl-D
# Owner: CN=....
# Issuer: ....
# ....
# Or read from stdin by piping to another command (which just prints the cert(s) ). In this case we use openssl to fetch directly from a site and then print its info.
echo "" | openssl s_client -connect www.google.com:443 -prexit 2>/dev/null \
| sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' \
| cert-print
# Owner: CN=....
# Issuer: ....
# ....
이것은 단말기에서 사용하기 쉽습니다.
$ echo '1\n2\n3\n' | while read -r; do echo $REPLY; done
1
2
3
나는 이 대답들 중 어느 것도 받아들일 수 없다고 생각한다.특히 승인된 응답은 첫 번째 명령줄 파라미터만 처리하고 나머지는 무시합니다.에뮬레이트하려고 하는 Perl 프로그램은 모든 명령줄 파라미터를 처리합니다.그래서 받아들여진 답변은 질문에 대답조차 하지 않습니다.
다른 응답은 Bash 확장자를 사용하거나 불필요한 'cat' 명령을 추가하거나 입력에서 출력으로 에코하는 단순한 경우에만 작동하거나 불필요하게 복잡합니다.
하지만, 그들이 나에게 아이디어를 줬기 때문에 나는 그들을 믿어야 한다.자세한 답변은 다음과 같습니다.
#!/bin/sh
if [ $# = 0 ]
then
DEFAULT_INPUT_FILE=/dev/stdin
else
DEFAULT_INPUT_FILE=
fi
# Iterates over all parameters or /dev/stdin
for FILE in "$@" $DEFAULT_INPUT_FILE
do
while IFS= read -r LINE
do
# Do whatever you want with LINE here.
echo $LINE
done < "$FILE"
done
「」를 할 수 .stdin/dev 디렉토리의 디바이스:
cat /dev/stdin' 항목에 대해 $item을 에코합니다.done
그리고...
while read line
do
echo "$line"
done < "${1:-/dev/stdin}"
다음과 같은 결과를 얻었습니다.
표준 입력에서 1265자를 무시했습니다.파이프 연결 입력 처리 방법을 알려면 "stdin" 또는 "-"를 사용합니다.
다음으로 다음으로 결정:
Lnl=$(cat file.txt | wc -l)
echo "Last line: $Lnl"
nl=1
for num in `seq $nl +1 $Lnl`;
do
echo "Number line: $nl"
line=$(cat file.txt | head -n $nl | tail -n 1)
echo "Read line: $line"
nl=$[$nl+1]
done
용도:
for line in `cat`; do
something($line);
done
언급URL : https://stackoverflow.com/questions/6980090/how-to-read-from-a-file-or-standard-input-in-bash
'programing' 카테고리의 다른 글
| Git 태그의 이름을 바꾸려면 어떻게 해야 하나요? (0) | 2023.04.19 |
|---|---|
| 프로그래밍 방식으로 segue 작성 (0) | 2023.04.14 |
| 'Get-ADUser' 용어가 cmdlet 이름으로 인식되지 않습니다. (0) | 2023.04.14 |
| Excel에서 상위 5개 최대값 추출 (0) | 2023.04.14 |
| 파워셸:스크립트에 오류가 표시되지 않도록 하려면 어떻게 해야 합니까? (0) | 2023.04.14 |