구분 기호 없이 두 파일의 특정 위치를 비교하는 방법

구분 기호 없이 두 파일의 특정 위치를 비교하는 방법

두 파일을 한 줄씩 비교해야 합니다. 나는 다른 줄만 출력하고 싶지만 차이점을 판단할 때 문자 4-6과 10-12는 무시해야 합니다. 특정 필드 구분 기호 등이 없습니다.

예:

  • 파일 1
    abc123def999
    ghi456klm999
    nop789qrs999
    
  • 파일 2
    abc000def000
    xxx000yyy000
    nop000qrs000
    

이 예에서는 두 번째 행만 달라야 합니다.

read파일에 수백만 개의 레코드가 있기 때문에 루프가 파일을 한 줄씩 구문 분석하는 것을 원하지 않습니다 .

답변1

GNU awk를 FIELDWIDTHS 매개변수로 사용:

$ paste file[12] |
    awk -v FIELDWIDTHS='3 3 3 3 1 3 3 3 3' '$1!=$6 || $3!=$8'
ghi456klm999    xxx000yyy000

paste여기서는 두 파일을 나란히 붙여넣는 명령을 사용합니다 . 그런 다음 awk의 FIELDWIDTHS 매개변수를 사용하여 필드 길이를 정의하므로 두 파일의 행이 고정 길이라고 가정하고 여기에서 관련 필드의 차이점을 비교합니다. 한 줄씩 수행됩니다.

또는 모든 쉘에서 awk를 사용하십시오.

$ paste file[12] |
    awk 'function key(s){return substr(s,1,3) substr(s,7,3)} key($1) != key($2)'
ghi456klm999    xxx000yyy000

답변2

예상되는 출력을 표시하지 않았고 요구 사항이 무엇인지 실제로 알려주지 않았으므로 다음은 모든 Unix 시스템의 모든 쉘에서 awk를 사용하여 원하는 것이 무엇인지 추측합니다.

$ cat tst.awk
{ key = substr($0,1,3) substr($0,7,3) }
NR == FNR {
    a[key]
    next
}
!(key in a)

$ awk -f tst.awk file1 file2
xxx000yyy000

$ awk -f tst.awk file2 file1
ghi456klm999

답변3

두 파일 모두 "수백만 개의 레코드"를 가지고 있습니까? 더 짧은 파일을 선택하고 각 줄을 읽은 다음 " ^"(줄 시작) 으로 $시작하고 " "(줄 끝)으로 끝나는 정규식을 생성합니다. 검색 문자열은 그 사이에 있습니다. 무시할 위치를 " ."(정규식 "모든 단일 문자와 일치")로 설정합니다. 예를 들어" ^abc...def...$". 임시 파일( file1.tmp)에 저장합니다(수백만?). 모든 줄을 처리하면 in에서 grep -E -f file1.tmp file2정규식을 검색합니다.file1.tmpfile2

답변4

방법 1)perl

unpack기능은 Perl 환경 트레이에 제공된 형식을 기반으로 특정 범위의 문자를 추출하므로 이러한 상황에 가장 적합합니다. (A3x3)2A*=> 3개의 ASCII 문자를 선택한 다음 3개의 문자를 건너뜁니다. 이 과정을 다시 반복하고 남은 것을 가져옵니다.

fmt='(A3x3)2A*' \
perl -nse 'print if "@{[unpack($ENV{fmt})]}" ne
"@{[unpack($ENV{fmt},scalar(<STDIN>))]}";
' -- -\"= File1 < File2
ghi456klm999

방법-2)paste+GNU sed

붙여넣기는 두 파일의 해당 줄을 탭으로 구분하여 나란히 배치합니다. 따라서 파일에 탭이 없어야 한다고 가정합니다. 그런 다음 두 파일의 데이터에서 4-6 및 10-12 문자를 동일한 문자 "."로 바꿉니다. 라인을 비교하기 전에 Ines가 일치하지 않으면 file1 줄을 인쇄합니다.

# helper vars aid in writing sed code
x3='...'
A3="($x3)"
A3x3=$A3$x3
srch="^$A3x3$A3x3"
repl="\\1$x3\\2$x3"

paste File1 File2 |
sed -En 'y/\t/\n/;h
  '"s/$srch/$repl/Mg"'
  /^(.*)\n\1$/d;g;P
' -

방법-3)Python

내장된 zip 기능은 두 파일의 줄을 나란히 봅니다.

python3 -c 'import sys
# skip chars: 4-6 10-12
AoT = [(0,3),(6,9),(12,None)] # array of tuples

fx = lambda t: \
  a[t[0]:t[1]] != b[t[0]:t[1]]

ifile1,ifile2 = sys.argv[1:]
with open(ifile1) as f1,\
     open(ifile2) as f2:
  for a,b in zip(f1,f2):
    if any(map(fx,AoT)):
      print(a,end="")
' File1 File2

관련 정보