Bash에서 파일 내용을 루프하는 중
Bash를 사용하여 텍스트 파일의 각 행을 반복하려면 어떻게 해야 합니까?
이 스크립트의 경우:
echo "Start!"
for p in (peptides.txt)
do
echo "${p}"
done
화면에 다음과 같은 출력이 표시됩니다.
Start!
./runPep.sh: line 3: syntax error near unexpected token `('
./runPep.sh: line 3: `for p in (peptides.txt)'
에 좀 더 것을 .$p
을 참조해 주십시오.)
환경변수 SHEL은 (env에서) 다음과 같습니다.
SHELL=/bin/bash
/bin/bash --version
★★★★
GNU bash, version 3.1.17(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
cat /proc/version
★★★★
Linux version 2.6.18.2-34-default (geeko@buildhost) (gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)) #1 SMP Mon Nov 27 11:46:27 UTC 2006
파일이 펩타이드화 됩니다.txt의 내용:
RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL
한 가지 방법은 다음과 같습니다.
while read p; do
echo "$p"
done <peptides.txt
코멘트에서 지적된 바와 같이, 이것은 선행 공백을 잘라내고, 백슬래시 시퀀스를 해석하고, 끝줄 피드가 없는 경우 마지막 줄을 건너뛸 수 있는 부작용이 있습니다.문제가 있는 경우는, 다음의 작업을 실시할 수 있습니다.
while IFS="" read -r p || [ -n "$p" ]
do
printf '%s\n' "$p"
done < peptides.txt
예외적으로 루프 본문이 표준 입력에서 읽을 수 있는 경우 다른 파일 기술자를 사용하여 파일을 열 수 있습니다.
while read -u 10 p; do
...
done 10<peptides.txt
여기서 10은 그냥 임의의 숫자입니다(0, 1, 2와는 다릅니다).
cat peptides.txt | while read line
do
# do something with $line here
done
및 원라이너 모델:
cat peptides.txt | while read line; do something_with_$line_here; done
이러한 옵션은 후행 피드가 없는 경우 파일의 마지막 줄을 건너뜁니다.
이 문제를 회피할 수 있는 방법은 다음과 같습니다.
cat peptides.txt | while read line || [[ -n $line ]];
do
# do something with $line here
done
옵션 1a: 루프 중: 한 번에 한 줄씩:입력 리다이렉션
#!/bin/bash
filename='peptides.txt'
echo Start
while read p; do
echo "$p"
done < "$filename"
옵션 1b: 루프 중: 한 번에 한 줄씩:
파일 디스크립터(이 경우는 파일 디스크립터 #4)에서 읽어낸 파일을 엽니다.
#!/bin/bash
filename='peptides.txt'
exec 4<"$filename"
echo Start
while read -u4 p ; do
echo "$p"
done
이는 다른 답변과 다를 바 없지만 공백이 없는 파일에서 작업을 수행하는 또 다른 방법입니다(댓글 참조).스크립트 파일을 따로 사용하지 않고 텍스트 파일의 목록을 한 줄씩 읽어야 하는 경우가 많습니다.
for word in $(cat peptides.txt); do echo $word; done
이 형식을 사용하면 모든 것을 하나의 명령줄에 저장할 수 있습니다."echo $word" 부분을 원하는 대로 변경하면 세미콜론으로 구분된 여러 명령을 실행할 수 있습니다.다음 예제에서는 파일 내용을 인수로 사용하여 작성한 다른 두 스크립트에 대한 내용을 보여 줍니다.
for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done
또는 이것을 스트림에디터(learn sed)와 같이 사용하는 경우는, 다음과 같이 출력을 다른 파일에 덤프 할 수 있습니다.
for word in $(cat peptides.txt); do cmd_a.sh $word; cmd_b.py $word; done > outfile.txt
한 줄에 한 단어로 작성한 텍스트 파일을 사용한 적이 있기 때문에 위와 같이 사용하고 있습니다.(댓글 참조) 단어/줄을 분할하지 않는 공백이 있는 경우, 조금 더 보기 흉해지지만 동일한 명령어는 다음과 같이 작동합니다.
OLDIFS=$IFS; IFS=$'\n'; for line in $(cat peptides.txt); do cmd_a.sh $line; cmd_b.py $line; done > outfile.txt; IFS=$OLDIFS
이렇게 하면 셸이 공백이 아닌 줄바꿈으로만 분할하도록 지시하고 환경을 이전 상태로 되돌립니다.다만, 이 시점에서, 모든 것을 한 줄에 짜넣는 것보다, 셸 스크립트에 짜넣는 것을 고려해 보는 것이 좋을지도 모릅니다.
행운을 빌어요!
다른 답변에서는 다루지 않는 몇 가지 사항이 더 있습니다.
구분된 파일에서 읽기
# ':' is the delimiter here, and there are three fields on each line in the file
# IFS set below is restricted to the context of `read`, it doesn't affect any other code
while IFS=: read -r field1 field2 field3; do
# process the fields
# if the line has less than three fields, the missing fields will be set to an empty string
# if the line has more than three fields, `field3` will get all the values, including the third field plus the delimiter(s)
done < input.txt
프로세스 대체를 사용하여 다른 명령어 출력에서 읽기
while read -r line; do
# process the line
done < <(command ...)
이 더 command ... | while read -r line; do ...
왜냐하면 여기서 while 루프는 후자의 경우와 같이 서브셸이 아닌 현재 셸에서 실행되기 때문입니다.루프가 기억되지 않는 동안 내부에서 변경된 변수는 관련 게시물을 참조해당 게시물은 다음과 같습니다.
입력: Null " " " " )에서 .find ... -print0
while read -r -d '' line; do
# logic
# use a second 'read ... <<< "$line"' if we need to tokenize the line
done < <(find /path/to/dir -print0)
관련: BashFAQ/020 - 줄 바꿈, 공백 또는 둘 다 포함된 파일 이름을 검색하여 안전하게 처리하는 방법 확인.
한 번에 두 개 이상의 파일에서 읽기
while read -u 3 -r line1 && read -u 4 -r line2; do
# process the lines
# note that the loop will end when we reach EOF on either of the files, because of the `&&`
done 3< input1.txt 4< input2.txt
여기 @chepner의 답변에 근거합니다.
-u
쾅쾅 때리다의 경우,각은 POSIX 「」와 .read -r X <&3
.
파일 전체를 어레이로 읽기 (4 이전 버전의 Bash)
while read -r line; do
my_array+=("$line")
done < my_file
파일이 불완전한 행(마지막에 줄바꿈이 누락됨)으로 끝나는 경우:
while read -r line || [[ $line ]]; do
my_array+=("$line")
done < my_file
파일 전체를 어레이로 읽기(Bash 버전 4x 이후)
readarray -t my_array < my_file
또는
mapfile -t my_array < my_file
그리고 나서.
for line in "${my_array[@]}"; do
# process the lines
done
빌트인에 대한 내용은 를 참조하십시오.
read
★★★★★★★★★★★★★★★★★」readarray
- GNU - GNU- BashFAq/001 - 파일(데이터 스트림, 변수)을 한 줄씩(및/또는 필드별로) 읽는 방법
관련 투고:
다음과 같이 while loop을 사용합니다.
while IFS= read -r line; do
echo "$line"
done <file
주의:
를
IFS
제대로 하면 움푹 패인 부분이 없어집니다.
읽기를 줄바꿈 문자로 구분하지 않으려면 다음을 사용하십시오.
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "$line"
done < "$1"
그런 다음 파일 이름을 매개 변수로 하여 스크립트를 실행합니다.
다음과 같은 파일이 있다고 가정합니다.
$ cat /tmp/test.txt
Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR
많은 Bash 솔루션에 의해 읽혀지는 파일 출력의 의미를 변경하는 4가지 요소가 있습니다.
- 빈 줄 4;
- 두 줄의 선행 또는 후행 공간
- 개별 라인의 의미 유지(즉, 각 라인은 기록)
- 회선 6이 CR로 종단되지 않았습니다.
CR 없이 빈 줄과 끝 줄을 포함하는 텍스트 파일을 한 줄씩 보려면 while loop을 사용하고 최종 줄에 대한 대체 테스트를 수행해야 합니다.
할 수 .cat
( ) :
1) 마지막 줄과 선행 및 후행 공백이 없어집니다.
$ while read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
경우)while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
및되지 않은 경우 이 손실됩니다.
2) 2) 프로세스 대체 cat
1kg의 전체 파일을 읽으며 개별 라인의 의미를 잃게 됩니다.파일 전체를 단숨에 읽어내 각 행의 의미를 잃게 됩니다.
$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR'
()) 제) 우 했 경) ,"
부에서$(cat /tmp/test.txt)
한 마디보다는 파일 단어를 읽습니다.한 번에 읽는 것보다 한 단어씩 읽는 거야.또한, 도... is또) also probably) not것 intended모아...도만 what다니?
파일을 한 줄씩 읽고 모든 간격을 유지하는 가장 강력하고 간단한 방법은 다음과 같습니다.
$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
' Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space '
'Line 6 has no ending CR'
선두와 거래 공간을 분리하려면 두 래 간 거 하 을 려 if you and the면 spaces leading trading)IFS=
삭제:
$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
'Line 6 has no ending CR'
)\n
포식스에 오는 것을 수 \n
없다|| [[ -n $line ]]
while
를 선택합니다.
사용하는 것을 좋아합니다.xargs
while
xargs
line 친화적입니다.
cat peptides.txt | xargs -I % sh -c "echo %"
★★★★★★★★★★★★★★★★ xargs
에을 더할 도 있습니다.-t
valid및 검 ation and -p
이것이 가장 간단한 답변일 수도 있고 모든 경우에 효과가 있는 것은 아닐 수도 있지만, 나에게는 매우 효과적입니다.
while read line;do echo "$line";done<peptides.txt
공백 괄호로 둘러싸야 하는 경우:
while read line;do echo \"$line\";done<peptides.txt
아, 이것은 가장 많이 투표된 답변과 거의 비슷하지만, 모두 한 줄에 있습니다.
#!/bin/bash
#
# Change the file name from "test" to desired input file
# (The comments in bash are prefixed with #'s)
for x in $(cat test.txt)
do
echo $x
done
다른 프로그램 출력의 행을 루프하고, 서브스트링을 체크하고, 변수에서 큰따옴표를 삭제하고, 해당 변수를 루프 밖에서 사용하는 예를 소개합니다.많은 분들이 조만간 이런 질문을 하실 것 같아요.
##Parse FPS from first video stream, drop quotes from fps variable
## streams.stream.0.codec_type="video"
## streams.stream.0.r_frame_rate="24000/1001"
## streams.stream.0.avg_frame_rate="24000/1001"
FPS=unknown
while read -r line; do
if [[ $FPS == "unknown" ]] && [[ $line == *".codec_type=\"video\""* ]]; then
echo ParseFPS $line
FPS=parse
fi
if [[ $FPS == "parse" ]] && [[ $line == *".r_frame_rate="* ]]; then
echo ParseFPS $line
FPS=${line##*=}
FPS="${FPS%\"}"
FPS="${FPS#\"}"
fi
done <<< "$(ffprobe -v quiet -print_format flat -show_format -show_streams -i "$input")"
if [ "$FPS" == "unknown" ] || [ "$FPS" == "parse" ]; then
echo ParseFPS Unknown frame rate
fi
echo Found $FPS
루프 외부에서 변수를 선언하고 값을 설정하고 루프 외부에서 사용하려면 done << "$(...)" 구문이 필요합니다.응용 프로그램은 현재 콘솔의 컨텍스트 내에서 실행해야 합니다.명령어 주위에 따옴표를 붙이면 출력 스트림의 새로운 행이 유지됩니다.
하위 문자열에 대한 루프 일치는 name=value pair를 읽고, 마지막 = 문자의 오른쪽 부분을 분할하고, 첫 번째 따옴표를 삭제하고, 마지막 따옴표를 삭제하며, 다른 곳에서 사용할 깨끗한 값을 제공합니다.
조금 늦었지만 누군가에게 도움이 될지도 모른다는 생각에 답변을 덧붙입니다.또한 이것이 최선의 방법이 아닐 수도 있습니다. head
는 명어는 command command command command command command command command command command 와 함께 사용할 수 .-n
파일 시작부터n 행을 읽는 인수 등tail
명령어를 사용하여 아래에서 읽을 수 있습니다.파일에서 n번째 행을 가져오려면 n개의 행을 선두로 하고 데이터를 파이핑된 데이터에서 한 줄만 테일링합니다.
TOTAL_LINES=`wc -l $USER_FILE | cut -d " " -f1 `
echo $TOTAL_LINES # To validate total lines in the file
for (( i=1 ; i <= $TOTAL_LINES; i++ ))
do
LINE=`head -n$i $USER_FILE | tail -n1`
echo $LINE
done
@Peter: 잘 될 것 같은데...
echo "Start!";for p in $(cat ./pep); do
echo $p
done
그러면 출력이 반환됩니다.
Start!
RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL
xargs를 사용하는 또 다른 방법
<file_name | xargs -I {} echo {}
echo는 다른 명령어로 대체하거나 더 많은 파이프를 연결할 수 있습니다.
p in 'cat 펩타이드.txt가 "${p}"를 에코합니다.
언급URL : https://stackoverflow.com/questions/1521462/looping-through-the-content-of-a-file-in-bash
'programing' 카테고리의 다른 글
준비 영역의 파일에 git diff 표시 (0) | 2023.04.09 |
---|---|
Postgres에 대량 삽입하는 가장 빠른 방법은 무엇입니까? (0) | 2023.04.09 |
텍스트 및 파일스트림을 통해 openpyxl 파일 저장 (0) | 2023.04.09 |
WPF UserControl은 어떻게 WPF UserControl을 상속합니까? (0) | 2023.04.09 |
R의 두 목록을 결합하는 방법 (0) | 2023.04.09 |