첫 번째 파일의 특정 열과 부분적으로 일치할 수 있는 다른 파일의 패턴을 기반으로 파일에서 행을 제거합니다.

첫 번째 파일의 특정 열과 부분적으로 일치할 수 있는 다른 파일의 패턴을 기반으로 파일에서 행을 제거합니다.

비슷한 답변을 검색했지만 부분 일치 문제를 해결한 답변이 없습니다. 스키마 파일은 file2이고 삭제할 행은 file1.csv에 있습니다. 이는 여기에 표시된 것보다 더 많은 열이 포함된 상당히 큰 파일입니다.

file1.csv에 다음 필드가 있습니다.

고쳐 쓰다:

Linking page,Last crawled
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
https://imgcop.com/img/Bwin-Mobile-App-77898390/,"Nov 17, 2018"
https://start.me/site/unibet.be?locale=fr,"Nov 17, 2018"
https://poker.partypoker402.com/en/blog/matt-savage-talks-wpt500.html,"Nov 17, 2018"

파일 2에는 다음이 포함됩니다.

https://roulette2.tk
paradisebingo.t
paradisebingo.tm
free-bwin.ro
sb288.co

OUTPUT
Linking page,Last crawled
Linking page,Last crawled
Linking page,Last crawled
Linking page,Last crawled
Linking page,Last crawled
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
https://start.me/discover/be/entertainment/betting?locale=ro,"Nov 17, 2018"
etc....

출력이 반복됩니다. 무엇이 잘못되었는지 잘 모르겠습니다.

awk 'FNR == NR{ neg[$1]; next } { for ( i in neg ) if ( $1 !~ i) print }' file2.txt FPAT='([^,]*)|("[^"]+")' file1.csv > out.csv

하지만 제대로 작동하지 못했습니다. 이상한 이유로 grep이 실패합니다.

grep -vwF -f file2 file1.csv > output.csv

답변1

당신이 한 일은 좋은 시도처럼 보이지만 정규식 일치 절이 원하는 방식으로 작동하지 않습니다. 에서는 찾으려는 값이 $2 !~ neg[$1]두 번째 파일에서 검색됩니다 .file1neg['156398439']$1아니요첫 번째. 따라서 귀하의 상태는 결코 일치하지 않습니다.

file1반복을 통해 작업 섹션 내에서 정규식 비교를 수행하기 위해 이와 같은 작업을 수행할 수 있습니다.

awk 'FNR == NR { neg[$1]; next }{ for ( i in neg ) if ( $2 !~ i) print  }' file2 FS="," file1

FS또한 이렇게 복잡한 정규식을 사용하여 CSV 파일의 제한을 해제할 수는 없을 것 같습니다 FS. 필드를 정의하는 방법이 아니라 분할할 제한 해제자를 정의하는 것을 기억하세요. 필드가 어떻게 생겼는지 설명하는 표현이 있는 것 같습니다. GNU에서는 awk다른 변수가 FPAT이러한 정규식을 정의할 수 있도록 허용합니다.

당신은 그것을 사용할 수 있습니다

awk 'FNR == NR { neg[$1]; next }{ for ( i in neg ) if ( $2 !~ i) print  }' file2 FPAT='([^,]*)|("[^"]+")' file1

답변2

이니안의 대답file2한 줄만 길면 잘 작동하며 보다 일반적인 답변을 시작하는 데 좋습니다. 하지만 난 믿어요

awk 'FNR == NR { neg[$1]; next } { ok=1; for (i in neg) if ($2 ~ i) ok=0; if (ok) print }' file2 FS="," file1

일반적으로 당신이 원하는 것을 할 것입니다. 답변과 마찬가지로 먼저 file2내용(에서 제거하려는 패턴 file)을 읽고 배열에 저장합니다. Inian의 답변처럼 다음과 같습니다 file1. 의 각 행에 대해 의 file1패턴을 반복합니다 file2. 우리는 라인이 괜찮다고 가정합니다. 어떤 패턴과 일치하면 그렇지 않습니다. 모든 패턴을 확인 후 문제가 없을 경우 인쇄해 드립니다.


FS=","그러나 나는 그것을 Inian이 하는 일이기 때문에 와 사이의 논쟁 으로 삼았습니다 . 아무것도 상관없어file2file1에프생산하다에스읽을 때 사용하는 구분 기호 file2는 표시되지 않고 file2쉼표를 포함하지 않는 한입니다. 따라서 "일반적인" 방식으로 필드 구분 기호를 지정하여 위의 내용을 약간 단순화할 수 있습니다. -F명령 시작 부분에 옵션을 추가하면 됩니다.

-에프,'FNR == NR { 부정 [$1]; 다음} { OK=1 for (i in neg) if ($2 ~ i) ok=0 if (OK) print}' file2 file1

-F","원하는 경우 이를 사용할 수 있습니다.


이 테스트는 FNR == NR너무 대중적이고 흔해서 우리는 아무 생각 없이 사용합니다.  FNR줄 번호(일명 레코드 번호)입니다.현재 파일에서는NR줄 번호 입니다모든 입력에 걸쳐.  예를 들어,

$ cat cats
Felix
Garfield
Heathcliff

$ cat dogs
Lassie
Marmaduke
Snoopy

$ awk '{ print FNR, NR, $0 }' cats dogs
1 1 Felix
2 2 Garfield
3 3 Heathcliff
1 4 Lassie
2 5 Marmaduke
3 6 Snoopy

…따라서 처리할 첫 번째 파일의 각 줄 FNR에 대한 합계는 동일하며 후속 파일에서는 동일하지 않습니다. NR그래서 우리는 이를 사용하여 FNR == NR첫 번째 파일이 처리되고 있는지 테스트합니다.

그러나 이것은 실제로 나쁜 습관입니다. 첫 번째 파일이 비어 있으면 어떻게 되나요?

$ cat unicorns

$ wc unicorns
      0       0       0 unicorns

$ awk '{ print FNR, NR, $0 }' unicorns dogs
1 1 Lassie
2 2 Marmaduke
3 3 Snoopy

FNR == NR그건 진실이야첫 번째 파일의 경우실제로 데이터가 있습니다.  당신 file2의 의지가 결코 비어 있지 않다면 이 질문을 무시할 수 있을 것입니다. 그러나 문제의 정의에 따르면 비어 있으면 아무것도 제거하지 않으므로 file2출력은 all 이 되어야 합니다 . file1그러나 아무것도 없이 위의 명령을 실행하면 다음과 같은 결과 file2가 나타납니다.아니요 왜냐하면 실제로 두 번째 파일( )을 읽을 때 첫 번째 파일 awk( )을 읽고 있다고 생각하기 때문입니다.file2file1

더 안전한 접근 방식은 파일 매개변수 사이에 값을 할당하는 것입니다.

awk -F, '문서! = 2{ 부정 [$1]; 다음} { ok=1; for (i in neg) if ($2 ~ i) ok=0 if (ok) 인쇄}' 파일파일=2파일 1

이 질문은 약간 모호합니다. "부분 일치"란 무엇을 의미합니까?정확히? Inian은 질문이 제안한 의미로 해석하기로 결정했습니다  grep. file2 두 번째 열의 값과 일치하는  값이 있는 경우file1 정규식으로는, 그런 다음 해당 줄을 삭제하십시오  file1. 하지만 두 가지 문제가 있습니다.

  1. 놀라운 요인. 질문에 있는 파일을 가져와서 추가했습니다.

    154376352,"http://sb288eco.tm","example4"
    

    에 줄을 서서 file1첫 번째 명령을 실행합니다. (from  )이 정규 표현식으로 처리되기 때문에 이 "example4"줄은 출력되지 않습니다 (여기서sb288.cofile2."모든 문자와 일치"를 의미함), match sb288eco.

    이것이 당신이 원하고 기대하는 일이라면 지금 이 글을 읽지 않는 것이 좋습니다.

  2. 정규식 처리에는 계산 비용이 많이 듭니다. 정규식은 구문 분석되고 처리되어야 합니다. 이는 단순한 문자열 비교보다 시간이 더 걸릴 수 있습니다.

위의 두 가지 문제를 테스트하여 해결할 수 있습니다.from 이 awk 함수의 file2 from 값에 존재합니다.file1index

awk -F, 'FILE != 2 { neg[$1];next} { OK=1;for (i는 음수입니다)if(index($2,i)>0)OK=0; if (ok) 인쇄 }' file2 FILE=2 file1

요약하자면,.게임 file2에는 딱 하나밖에 없습니다..file1, 다른 문자가 아닌 . 귀하의 데이터에 대해 위의 내용을 테스트하고 속도가 더 빠른지 확인하시기 바랍니다.


PS 답변을 게시한 이후에 파일 형식이 변경된 것을 방금 확인했습니다. 처음에는 값과 file2 값을 테스트하려고 합니다. 두번째열  file1. 이제 테스트하려는 것 같습니다.첫 번째열  file1. 이 변경 사항을 수용하려면 $2위 답변 중 하나와 비교한 섹션을 i사용하도록 변경해야 합니다 $1. 또는 전체 행을 테스트하려면 를  file1사용하십시오 $0.


따라서 결론적으로 다음을 사용하고 싶을 수도 있습니다.

awk -F, 'FILE != 2 { neg[$1]; next } { ok=1; for (i in neg) if (index($1,i) > 0) ok=0; if (ok) print }' file2 FILE=2 file1

당신의 명령대로. 가독성을 위해 줄 바꿈은 다음과 같습니다.

awk -F, 'FILE != 2 { neg[$1]; next }
                   {
                     ok=1
                     for (i in neg)
                             if (index($1,i) > 0) ok=0
                     if (ok) print
                   }' \
        file2 FILE=2 file1

관련 정보