2017-10-22 8 views
0

저는 쉘 스크립팅을 처음 사용하고 있으며 Korn 쉘 스크립트를 작성하고 있습니다.다중 grep 명령이있는 IF에서 NOT 연산자 사용

내 목표는 fileA.txt 4 별도의 파일 (의 그들 fileA.txt, fileB.txt, fileC.txtfileD.txt를 부르 자)에 각 행을 검색하는 것입니다. 다른 파일의 네 파일 모두에서 찾을 수없는 fileA.txt의 행에 대해 "찾을 수 없음"을 인쇄해야합니다.

다음 If 문을 작성했습니다. & &을 사용하는 4 개의 grep 명령을 결합하려고 시도하고 있으며 논리적 인 Not (!)를 수행하기 때문에 4 개의 파일 중 어느 것도 찾지 못한 행만 필요합니다.

for i in $(<fileA.txt); 
do 
    if !((grep -q $i fileB.txt) && (grep -q $i fileB.txt) && (grep -q $i fileC.txt) && (grep -q $i fileD.txt)); then 
     print "$i not found in either of 4 files" 
    fi 
done 

내가 구문에 분명히 틀린 점이 있지만 쉘 스크립팅의 초보자라는 것을 알고 있습니다. 알아낼 수 없습니다.

+0

fileB.txt를 두 번 확인했거나 fileA.txt를 의미 했습니까 ('i'는 fileA에서 찾을 수 있으므로 의미가 없습니다)? – chepner

답변

1

괄호는 필요 없습니다. 사실 &&을 사용하고 있으므로 grep에 3 번 별도로 전화 할 필요가 없습니다.

while IFS= read -r line; do 
    if ! grep -q "$i" fileB.txt fileC.txt fileD.txt; then 
    print "$i not found in any of the 3 files" 
    fi 
done < fileA.txt 

루프가 필요하지 않습니다. 이 패턴은 -f 옵션으로 덮여있다 : 그것은 당신이 묻는 질문에 대답, 따라서 SO 정책을 위반하지 않는

if ! grep -f fileA.txt fileB.txt fileC.txt fileD.txt; then 
    ... 
fi 
+0

정말 고마워요! 다른 파일에서 발견 된 각 줄마다 뭔가를해야하기 때문에 루프를 사용하고 있습니다. 그리고 while 루프를 사용하면 for 루프를 사용하는 것보다 이점이 있습니까? – lebowski

+0

[배쉬 FAQ 001] (http://mywiki.wooledge.org/BashFAQ/001)을 참조하십시오. – chepner

+1

그들은 실제로 동일하지 않습니다. 'grep -q x B C D'는 x가 파일 B C D의 _any_에서 발견되면 성공하지만'grep -q x B && grep -q x C && grep -q x D'는 x가 _every_ 파일에서 발견 된 경우에만 성공합니다. 그러나 전자가 실제로 OP가 원하는 것 인 것으로 보입니다. OTOH'grep -f A B C D'는 A의 패턴 중 _any_가 _any_ 파일에서 발견되면 성공합니다. –

2

하지만, 한 번에 AWK와 실제 문제를 해결하는 방법이 그 내가 할 수있는 ' 합리적인 의견에 t 적합 :

awk 'FNR==NR{a[$0];next} {for(p in a)if($0~p){delete a[p]}} \ 
    END{for(p in a)print "notfound: ",p}' patternfile data1 data2 data3 etc 

notfound: 단지 명확성을 위해, 당신은 변경하거나 필요에 따라 생략합니다.

출력 값 (모든 데이터 파일에서 발견되지 않은 패턴)은 반드시 패턴 파일에서와 동일한 순서로 있지는 않습니다. 만약 당신이 그것에 대해 걱정한다면 :

awk 'FNR==NR{a[$0]=FNR;next} {for(p in a)if($0~p){delete a[p]}} \ 
    END{for(p in a)print a[p],p}' patternfile data1 data2 data3 etc | sort -k1n | cut -f2- 
# or in GNU awk v4+ only 
awk 'FNR==NR{a[$0]=FNR;next} {for(p in a)if($0~p){delete a[p]}} \ 
    END{PROCINFO["sorted_in"]="@val_num_asc";for(p in a)print p}' patternfile data1 data2 data3 etc 

당신의 질문은 또한 'lines'에 대해서 모호합니다. 패턴 파일의 각 라인이 데이터 파일 중 하나에이라는 으로 나타나야하거나 라인 내에서 발생할 수 있지만 반드시 전체 라인에서 발생할 수는 없습니까? 또한 패턴 파일의 값만 데이터 문자입니까 아니면 데이터의 다른 것과 일치하는 특수 문자입니까? grep 기본값으로 예를 들어 당신이 게시 된 경우 (이나와awk ~ 내가 위에서 가지고) patternfile 해당 항목이 데이터 파일은 다음 줄의 포함되어있는 경우 발견 간주됩니다 boojum.. 라인이 포함 된 경우 :

boojum.. 
boojumXY 
the snark was a boojum!! 

abc 
abcdefghi 

을하지만 일치하지 않습니다 : 다음 patternfile 라인 OTOH ^abc이 일치합니다

^abc 

에서 -x 옵션을 사용하고 리터럴 (정규 표현식 제외)을 -F 또는 둘 모두와 일치시킬 수 있습니다. 이것도 awk에서 얻을 수 있지만 다르게.