파일에서 특정 패턴과 일치하는 텍스트를 제거하는 방법

파일에서 특정 패턴과 일치하는 텍스트를 제거하는 방법

두 파일(fileA와 fileB)의 차이점을 확인하기 위해 비교하고 싶습니다. fileA는 템플릿 파일과 같고 fileB는 비교하려는 파일입니다. 차이점을 찾을 때마다 해당 차이점을 fileC에 출력하고 싶습니다.

어려운 점은 fileA와 fileB에 일부 데이터(시간, 날짜 및 무작위로 생성된 ID 코드)가 항상 다른 일부(전부는 아님) 행이 포함되어 있다는 것입니다. 그러나 유일한 차이점은 시간, 날짜 및 ID 코드뿐인 fileC에 행을 출력하고 싶지 않습니다.

그래서 내가 원하는 것은 fileB에 나타나는 모든 줄에서 시간, 날짜 및 ID 코드를 제거한 다음(fileA에서 수동으로 이 작업을 수행할 수 있음) fileB와 비교하고 다른 줄을 fileC에 출력하는 것입니다.

삭제할 텍스트는 항상 특정 패턴을 따른다는 점에 유의하세요. 그래서 grep과 이러한 패턴을 사용하여 텍스트를 찾을 수 있지만 제거하는 방법을 모르겠습니다...

다음은 내가 의미하는 바를 설명하는 두 파일의 예입니다.

  • 문서 B

    qaqa rara
    abc 10:12:25 08/20/2014 123456 def
    ghi fff ddd
    jkl 09:20:40 08/20/2014 978645 dfdf gggg
    
  • 파일 A

    qaqa rara
    abc 10:32:15 07/15/2014 121456 xxx
    ghi eee ddd
    jkl 10:01:22 07/15/2014 971645 dfdf gggg
    

시간(예: 10:12:25), 날짜(예: 08/20/2014) 또는 ID 코드(예: 123456)를 무시하고 위 ​​두 파일의 차이점을 찾아 차이점을 fileC에 출력하고 싶습니다.

두 행이 다르기 때문에 2행과 3행이 됩니다. 두 파일의 라인 1은 동일합니다. 시간, 날짜, ID 정보를 제거하면 두 파일의 4번째 줄은 동일합니다.

답변1

타임스탬프가 일관된 형식인 경우 diff 방법(예: sed 사용)을 사용하여 파일을 처리하기 전에 이를 제거할 수 있습니다.

diff <(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileA) <(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileB)

제공한 입력 파일에 대해 테스트합니다.

$ diff \
<(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileA) \
<(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileB)
2,3c2,3
< abc xxx
< ghi eee ddd
---
> abc def
> ghi fff ddd

답변2

결과를 얻는 가장 간단한 명령은 다음과 같습니다

$ diff <(tr -s "[0-9],:,/" " " < 파일 A) <(tr -s "[0-9],:,/" " " < 파일 B)

명령은 매우 간단하며 복잡한 정규 표현식이 없습니다.

샘플 출력은 다음과 같습니다

2,3c2,3
< abc xxx
< ghi eee ddd
---
> abc def
> ghi fff ddd

이것이 당신이 원하는 것이기를 바랍니다.

답변3

diff \
<(sed -r 's\[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{6} \\' fileA) \
<(sed -r 's\[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{6} \\' fileB) \
| egrep '^> ' | sed -r 's/^> //' > fileC

설명하다

fileA 및 fileB에서 OP의 질문에 제공된 관련없는 부분을 제거하고 diff에 입력하십시오.

diff는 ">" 앞에 변경된 부분을 출력하므로 변경 사항을 제외한 다른 모든 내용은 무시됩니다.

마지막으로 출력에서 ​​선행 ">"를 제거하고 질문에 따라 fileC에 저장합니다.

처음에는 약간 다르게 했지만 관련 없는 부분에서 파일이 다를 수 있다는 점을 발견했기 때문에 사후 스트립이 아닌 사전 스트립을 수행해야 합니다. 그렇지 않으면 관련 부분만 있을 때 diff가 실제로 변경되지 않은 정보를 출력하게 됩니다. 고려.

주어진 예제 입력은 cat fileC다음과 같습니다.

abc def
ghi fff ddd

sed 명령은 관련 없는 데이터를 설명하는 제공된 정규식을 검색하고 이를 빈 문자열로 대체합니다. 즉, 삭제합니다.

답변4

{   paste -d\| /dev/fd/3 /dev/fd/4 |
    sed '/\([^ ]*\) [0-9:/ ]*\(.*\)|\1 .*\2/d;=' |
    sed 'N;s/\(\n\)\(.*\)|/:\tFILEA: \2\1\tFILEB: /'
} 3<<\FILEA 4<<\FILEB
qaqa rara
abc 10:12:25 08/20/2014 123456 def
ghi fff ddd
jkl 09:20:40 08/20/2014 978645 dfdf gggg
FILEA
qaqa rara
abc 10:32:15 07/15/2014 121456 xxx
ghi eee ddd
jkl 10:01:22 07/15/2014 971645 dfdf gggg
FILEB

산출

2:      FILEA: abc 10:12:25 08/20/2014 123456 def
        FILEB: abc 10:32:15 07/15/2014 121456 xxx
3:      FILEA: ghi fff ddd
        FILEB: ghi eee ddd

시간과 날짜를 제거할 필요는 없습니다. 이를 구성하는 문자가 신뢰할 수 있는 한 큰 방해가 되지는 않습니다.

위 파이프라인에서는 pastefrom의 해당 줄이 먼저 FILEB단일 구분 기호를 사용하여 각 줄의 끝에 추가된 다음 결과가 인쇄됩니다.FILEA|stdout

sed스트림을 선택하고 비교하십시오.

  • 공백이 아닌 0개 이상의 문자로 구성된 첫 번째 시퀀스(로 인용 \1)

  • 다음 시퀀스 사이에 나타나는 모든 문자:(로 인용 \2)

    • 하나 이상의 <space>문자, 다음 문자 중 0개 이상:

    • <space>수치

    • <digit>수치

    • <:colon>수치

    • </slash>수치

  • |줄에 나타나는 마지막 문자 까지(포함하지 않음)

...그리고 |\1.*\2. 일치하면 sed행을 삭제하십시오. 그렇지 않은 경우 줄 번호 앞에 줄이 있는 줄을 인쇄합니다.

마지막 sed과정은 출력물을 아름답게 만드는 것입니다.(나는 희망).

관련 정보