두 파일의 줄을 병렬로 반복합니다.


18

내가 만들고있는 스크립트의 목적은 두 개의 일련의 파일을 비교하는 것입니다. 파일 이름 자체는 한 줄에 하나씩 두 개의 별도 파일에 저장됩니다. 내 생각은 while read각 파일 이름 목록에 하나씩 두 개의 루프 를 두는 것이지만 두 루프를 어떻게 혼합 할 수 있습니까?

while read compareFile <&3; do     
 if [[ ! $server =~ [^[:space:]] ]] ; then  #empty line exception
    continue
 fi   
    echo "Comparing file - $compareFile"
 if diff "$compareFile" _(other file from loop?_) >/dev/null ; then
     echo Same
 else
      echo Different
 fi 
done 3</infanass/dev/admin/filestoCompare.txt

두 개의 다른 읽기 루프를 통해 두 개의 서로 다른 목록의 파일을 동시에 비교할 수 있어야합니다. 이것이 가능합니까?


이 대본을 도전의 왕으로 만들려고합니까? 그렇지 않은 경우 파일과 같은 강력한 도구가 이미 존재합니다 diff.
lgeorget

" 도전의 종류 ", 죄송합니다
lgeorget

OP가 사용하고있는 @lgeorget diff.
terdon

아, 두 목록의 파일 . 쓸모없는 의견에 대해 죄송합니다 ...
lgeorget

답변:


20

두 개의 루프가 필요하지 않습니다. 하나의 루프에서 두 파일을 읽어야합니다.

while read compareFile1 <&3 && read compareFile2 <&4; do     
 if [[ ! $server =~ [^[:space:]] ]] ; then  #empty line exception
    continue
 fi   
    echo "Comparing file - $compareFile"
 if diff "$compareFile1" "$compareFile2" >/dev/null ; then
     echo Same
 else
      echo Different
 fi 
done 3</infanass/dev/admin/filestoCompare.txt 4<other_file

코드 감사가 줄어 듭니다! 빈 루프 예외를 동시에 처리하고 두 루프에 대해 어떻게 처리합니까?
mkrouse

@mkrouse, 나는 당신이 전에 그 $ server 변수로 무엇을했는지 모르지만, 한 변수에서 빈 줄을 테스트하면 다른 변수에서도 똑같이합니다.
psusi

7

방법 1 : 아는 것을 사용하십시오

하나의 파일을 반복하는 방법을 이미 알고 있으므로 파일을 결합한 다음 결합 된 파일을 처리 할 수 ​​있습니다. 이 명령은 paste두 파일을 한 줄씩 결합합니다. 두 파일에서 오는 줄 사이에 탭을 넣으 므로이 솔루션에서는 파일 이름에 탭이 없다고 가정합니다. 구분 기호를 변경할 수 있지만 파일 이름에없는 문자를 찾아야합니다.

paste -- "$list1.txt" "list2.txt" |
while IFS=$'\t' read -r file1 file2 rest; do
  diff -q -- "$file1" "$file2"
  case $? in
    0) status='same';;
    1) status='different';;
    *) status='ERROR';;
  esac
  echo "$status $file1 $file2"
done

빈 줄을 건너 뛰려면 paste한 파일의 빈 줄과 다른 파일의 빈 줄이 일치 할 수 있으므로 각 파일에서 개별적으로 수행해야 합니다. grep공백이 아닌 행을 필터링하는 데 사용할 수 있습니다 .

paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
  

두 파일의 길이가 서로 다르면 $file2어떤 목록이 먼저 끝나 든 관계없이 비어 있게됩니다.

방법 2 : 두 파일을 반복

while 루프 조건에서 원하는만큼 복잡한 명령을 넣을 수 있습니다. 넣으면 read file1 <&3 && read file2 <&4두 파일 모두 읽을 줄이있는 한, 즉 한 파일이 없어 질 때까지 루프가 실행됩니다.

while read -u 3 -r file1 && read -u 4 -r file2; do
  
done 3<list1..txt 4<list2.txt

빈 줄을 건너 뛰려면 두 파일을 독립적으로 건너 뛰어야하기 때문에 조금 더 복잡합니다. 쉬운 방법은 문제를 두 부분으로 나누는 것입니다. 한 파일에서 빈 줄을 건너 뛰고 빈 줄이 아닌 줄을 처리합니다. 빈 줄을 건너 뛰는 한 가지 방법 grep은 위와 같이 처리하는 것입니다. <리디렉션 연산자와 <(명령 의심을 시작하는 사이에 필요한 공간을 확인하십시오 .

while read -u 3 -r file1 && read -u 4 -r file2; do
  
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")

또 다른 방법은 read빈 줄을 건너 뛰고 동작하는 함수를 작성하는 것입니다 . 이 함수는 read루프 를 호출 하여 작동 할 수 있습니다 . 함수일 필요는 없지만 코드를 구성하고 코드를 두 번 호출해야하기 때문에 함수가 최선의 방법입니다. 함수에서 이름이 값인 변수의 값으로 평가 ${!#}되는 bash 구문의 인스턴스 ${!VARIABLE}입니다 VARIABLE. 여기서 변수는 #위치 매개 변수의 수를 포함 하는 특수 변수 이므로 ${!#}마지막 위치 매개 변수입니다.

function read_nonblank {
  while read "$@" &&
        [[ ${!#} !~ [^[:space:]] ]]
  do :; done
}
while read_nonblank -u 3 -r file1 && read_nonblank -u 4 -r file2; do
  
done 3<list1..txt 4<list2.txt

내가 읽기의 사용 등의 -u옵션
펠리페 알바레즈

1

한 가지 방법은 read -rajust 대신에 사용하는 것입니다 read. filestoCompare.txt파일 이름이 각각 포함 된 2 개의 열을 가정하면 read -ra두 열을 동시에 읽고 배열에 할당합니다 compareFile. 그런 다음 인덱스 0이 첫 번째 파일이되고 인덱스 1이 매번 두 번째 파일이되도록이 배열에 액세스 할 수 있습니다.while루프를 .

이 파일이 있다고 가정 filestoCompare.txt하면 다음이 포함됩니다.

file1 file2
file3 file4
file5 file6

이 파일을 통과하는 명령은 다음과 같습니다.

$ while read -ra a ; do printf "%s\t%s\n" ${a[0]} ${a[1]}; done < filestoCompare.txt
file1   file2
file3   file4
file5   file6

두 파일이 실제로 다음과 같은 별도의 파일 인 경우 :

#list1
file1
file2
file3

#list2
file4
file5
file6

다음과 같이 paste명령과 함께 결합 될 수 있습니다 .

$ paste list1 list2 > list1and2

list1and2의 내용은 다음과 같습니다.

$ cat list1and2
file1   file4
file2   file5
file3   file6

그러나 이것은 입력 형식이 아닙니다. 목록은 서로 다른 두 파일로되어 있습니다. join먼저 할 수 있습니다.
Gilles 'SO- 악마 그만해'

@Gilles-나는 그것이 입력 형식이 아니라는 것을 안다. 나는 심지어 "... filetoCompare.txt에 파일 이름이 각각 2 개의 열이 있다고 가정하면 ..."이라고 말했다. 귀하의 분쟁을 이해하고 동의하지 않습니다. OP는이 질문을 게시 한 이후로이 질문에 대한 추가 지침을 제공하지 않았습니다.
slm

@Gilles-명령 paste을 사용 하여 2 개의 파일을 결합하는 방법을 보여주는 예제를 추가하면 어떻게 됩니까? 당신이 unvovote 할 수 있습니까?
slm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.