중첩된 while 루프에서 두 개의 입력 파일을 동시에 읽을 수 있는 방법이 있는지 궁금합니다. 예를 들어 두 개의 파일 FileA
과 FileB
.
파일 A:
[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3
파일 B:
[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3
현재 예제 스크립트:
[jaypal:~/Temp] cat read.sh
#!/bin/bash
while read lineA
do echo $lineA
while read lineB
do echo $lineB
done < fileb
done < filea
구현하다:
[jaypal:~/Temp] ./read.sh
this is File A line1
this is File B line1
this is File B line2
this is File B line3
this is File A line2
this is File B line1
this is File B line2
this is File B line3
this is File A line3
this is File B line1
this is File B line2
this is File B line3
문제 및 원하는 결과:
그러면 FileA의 각 행에 대해 FileB가 완전히 반복됩니다. 계속, 중단, 종료를 사용해 보았지만 그 중 어느 것도 내가 원하는 결과를 얻지 못했습니다. 스크립트가 파일 A에서 한 줄만 읽은 다음 파일 B에서 한 줄을 읽은 다음 루프를 종료하고 파일 A의 두 번째 줄과 파일 B의 두 번째 줄을 계속 읽도록 하고 싶습니다. 다음 스크립트와 비슷한 것 -
[jaypal:~/Temp] cat read1.sh
#!/bin/bash
count=1
while read lineA
do echo $lineA
lineB=`sed -n "$count"p fileb`
echo $lineB
count=`expr $count + 1`
done < filea
[jaypal:~/Temp] ./read1.sh
this is File A line1
this is File B line1
this is File A line2
this is File B line2
this is File A line3
this is File B line3
while 루프를 사용하여 이를 달성할 수 있습니까?
답변1
첫 번째 파일에 특정 문자가 절대 나타나지 않도록 보장할 수 있다면 붙여넣기를 사용할 수 있습니다.
예를 들어, 이런 일은 절대 일어나지 않을 것이라고 확신합니다 @
.
paste -d@ file1 file2 | while IFS="@" read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done
문자가 첫 번째 파일에 나타나지 않는지 확인하는 것만으로도 충분합니다. 이는 마지막 변수를 read
채울 때 무시되기 때문입니다. IFS
따라서 두 번째 파일에서 발생하더라도 @
분할되지 않습니다.
더 깔끔한 코드를 얻기 위해 일부 bash 기능을 사용하고 기본 구분 기호 탭을 사용하여 붙여넣는 예:
while IFS=$'\t' read -r f1 f2
do
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done < <(paste file1 file2)
사용된 Bash 함수:ANSI C 문자열( $'\t'
) 그리고프로세스 교체( <(...)
) 도착하다서브셸에서 while 루프 문제 방지.
두 파일 모두에 어떤 문자도 나타나지 않을지 확실하지 않은 경우 두 개의 파일을 사용할 수 있습니다.파일 설명자.
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
printf 'f1: %s\n' "$f1"
printf 'f2: %s\n' "$f2"
done 3<file1 4<file2
많이 테스트되지 않았습니다. 빈 줄에서 중단될 수 있습니다.
파일 설명자 번호 0, 1, 2는 각각 stdin, stdout 및 stderr에 사용되었습니다. 파일 설명자 3 이상은 (일반적으로) 무료입니다. bash 매뉴얼은 "내부적으로 사용"되기 때문에 9보다 큰 파일 설명자를 사용하지 말라고 경고합니다.
열린 파일 설명자는 셸 기능과 외부 프로그램에 상속됩니다. 열린 파일 설명자를 상속하는 함수와 프로그램은 파일 설명자를 읽고 쓸 수 있습니다. 함수나 외부 프로그램을 호출하기 전에 불필요한 파일 설명자를 모두 닫도록 주의해야 합니다.
이것은 실제 작업(인쇄)이 메타 작업(두 파일을 한 줄씩 병렬로 읽는 작업)과 분리된 위와 동일한 프로그램입니다.
work() {
printf 'f1: %s\n' "$1"
printf 'f2: %s\n' "$2"
}
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
work "$f1" "$f2"
done 3<file1 4<file2
이제 우리가 작업 코드를 제어할 수 없고 코드가 어떤 이유로든 파일 설명자 3에서 읽으려고 한다고 가정해 보겠습니다.
unknowncode() {
printf 'f1: %s\n' "$1"
printf 'f2: %s\n' "$2"
read -r yoink <&3 && printf 'yoink: %s\n' "$yoink"
}
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
unknowncode "$f1" "$f2"
done 3<file1 4<file2
이는 예시 출력입니다. 첫 번째 파일의 두 번째 줄은 루프에서 "도난"되었습니다.
f1: file1 line1
f2: file2 line1
yoink: file1 line2
f1: file1 line3
f2: file2 line2
외부 코드(또는 해당 코드)를 호출하기 전에 파일 설명자를 닫는 방법은 다음과 같습니다.
while true
do
read -r f1 <&3 || break
read -r f2 <&4 || break
# this will close fd3 and fd4 before executing anycode
anycode "$f1" "$f2" 3<&- 4<&-
# note that fd3 and fd4 are still open in the loop
done 3<file1 4<file2
답변2
이 두 파일을 다른 위치에서 엽니다.파일 설명자. 내장된 파일의 입력을 read
연결하려는 파일의 설명자로 리디렉션합니다. bash/ksh/zsh에서는 read -u 3
대신 쓸 수 있습니다 read <&3
.
while IFS= read -r lineA && IFS= read -r lineB <&3; do
echo "$lineA"; echo "$lineB"
done <fileA 3<fileB
가장 짧은 파일이 처리되면 세그먼트가 중지됩니다. 바라보다두 개의 파일을 IFS while 루프로 읽는 중 - 이 경우 차이가 없는 결과를 얻을 수 있는 방법이 있습니까?두 파일이 끝날 때까지 계속 처리하려는 경우.
당신은 또한 볼 수 있습니다추가 파일 설명자는 언제 사용됩니까?파일 설명자에 대한 추가 정보 및"IFS=;" 대신 "IFS= 읽기"가 자주 사용되는 이유는 무엇입니까?에 대한 설명 IFS= read -r
.
답변3
다음 명령을 시도해 보십시오:
paste -d '\n' inp1.txt inp2.txt > outfile.txt
답변4
또는 bash의 mapfile 명령을 사용하여 파일을 배열 변수에 넣고 파일의 각 줄을 array[line_of_file_index]에 바인딩할 수 있다고 가정합니다. 그러나 Bash3 이상이나 Bash4에서만 작동하는지 확실하지 않습니다.