다른 줄에있는 파일의 여러 문자열에 대한 grep (예 : 줄 기반 검색이 아닌 전체 파일)?


85

나는 파일이 단어를 포함 grep으로 할 Dansk, Svenska또는 Norsk가능한 반환 코드로, 어떤 라인 (문자열이 포함되어 있다는 정보를 가지고 정말 단지 등 내 한 줄이 더 다음이를 조금 간다).

다음과 같은 줄이있는 많은 파일이 있습니다.

Disc Title: unknown
Title: 01, Length: 01:33:37.000 Chapters: 33, Cells: 31, Audio streams: 04, Subpictures: 20
        Subtitle: 01, Language: ar - Arabic, Content: Undefined, Stream id: 0x20, 
        Subtitle: 02, Language: bg - Bulgarian, Content: Undefined, Stream id: 0x21, 
        Subtitle: 03, Language: cs - Czech, Content: Undefined, Stream id: 0x22, 
        Subtitle: 04, Language: da - Dansk, Content: Undefined, Stream id: 0x23, 
        Subtitle: 05, Language: de - Deutsch, Content: Undefined, Stream id: 0x24, 
(...)

내가 원하는 의사 코드는 다음과 같습니다.

for all files in directory;
 if file contains "Dansk" AND "Norsk" AND "Svenska" then
 then echo the filename
end

이를 수행하는 가장 좋은 방법은 무엇입니까? 한 줄로 할 수 있습니까?

답변:


89

당신이 사용할 수있는:

grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska

숨겨진 파일에서도 찾으려면 :

grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska

영리한 솔루션; 한 가지 주목할 점은 (일반적으로 말하면 OP가 요청한 것과 관련이 없음) (개념적) 실패의 경우에도 전체 종료 코드0이라는 것입니다. 따라서 실패와 성공을 결정하는 데 관심이 있다면 stdout 출력이 비어 있는지 여부를 조사하거나 대신 @EddSteel의 접근 방식을 사용해야합니다.
mklement0

@mklement : Bash에서 PIPESTATUS배열은 파이프 라인 구성원의 종료 값을 포함합니다.
Dennis Williamson

@DennisWilliamson 알아서 반갑습니다, 감사합니다. 또 다른 옵션은 pipefail쉘 옵션을 (일시적으로) shopt -so pipefail
켜는 것입니다

4
당신은 사용 할 수 있습니다 grep -Zxargs -0귀하의 파일 이름은 공백을 포함 할 수 있습니다.
Ben Challenor 2013-06-25

1
파일이 많은 경우 "인수 목록이 너무 김"오류가 발생할 수 있습니다.
AnnanFay

23

bash와 grep을 사용하는 또 다른 방법 :

단일 파일 'test.txt'의 경우 :

  grep -q Dansk test.txt && grep -q Norsk test.txt && grep -l Svenska test.txt

test.txt파일에 세 가지가 모두 포함되어 있으면 인쇄 합니다 (조합에 관계없이). 처음 두 개의 greps는 아무것도 인쇄하지 않으며 ( -q) 마지막 두 개의 greps는 다른 두 개의 greps 가 통과 된 경우에만 파일을 인쇄합니다.

디렉토리의 모든 파일에 대해 수행하려면 다음을 수행하십시오.

   f in *; grep -q Dansk $ f && grep -q Norsk $ f && grep -l Svenska $ f; 끝난

하지만 grep을 세 번 실행할 필요가 없습니다.
쿠루미

1
패턴을 -e와 결합 할 수 있다는 것을 알고 있지만 grep만으로 접속사를 만드는 방법을 볼 수는 없습니다.
Edd Steel

1
큰; re for f ...: 공백 등이 포함 된 파일 이름이 올바르게 처리되는지 확인하기 "$f"보다는 (큰 따옴표) $f를 사용하십시오.
mklement0

@vmpstr에 비해이 접근 방식의 장점은 종료 코드가 모든 검색어가 발견되었는지 여부를 올바르게 반영한다는 것입니다.
mklement0

19
grep –irl word1 * | grep –il word2 `cat -` | grep –il word3 `cat -`
  • -i 검색 대소 문자를 구분하지 않습니다.
  • -r 폴더를 통해 파일 검색을 재귀 적으로 만듭니다.
  • -l 찾은 단어로 파일 목록을 파이프합니다.
  • cat - 다음 grep이 목록에 전달 된 파일을 살펴 보도록합니다.

1
이것은 가장 간단하고 직접적인 대답입니다. 매우 도움이되는 감사합니다!
majick

9

다른 줄에있는 파일의 여러 문자열을 grep하는 방법 (파이프 기호 사용) :

for file in *;do 
   test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done

메모:

  1. ""grep에 큰 따옴표를 사용하는 경우 다음 과 같이 파이프를 이스케이프해야합니다 \|. Dansk, Norsk 및 Svenska를 검색합니다.

  2. 한 줄에 하나의 언어 만 있다고 가정합니다.

연습 : http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/


Dansk Norsk와 Svenska가 모두 같은 줄에 나타나면 실패하지 않을까요?
vmpstr 2011 년

예.이 경우 실패합니다. 나는 언어가 한 줄에 하나씩 나타난다 고 가정했습니다.
Damodharan R

나만 가지고 Norsk있지만 세 줄로 된 경우에도 파일이 작성됩니다 .
Benjamin W.

6

ack를 사용 하면 정말 쉽게 할 수 있습니다 .

ack -l 'cats' | ack -xl 'dogs'
  • -l: 파일 목록 반환
  • -x: STDIN (이전 검색)에서 파일을 가져 와서 해당 파일 만 검색합니다.

그리고 원하는 파일을 얻을 때까지 계속 파이핑 할 수 있습니다.


이것을 시도하면 Unknown option: x. 이 x 플래그를 지원하는 특정 버전의 ack가 있습니까?
Hassan

4
awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }' 

그런 다음 쉘로 반환 값을 잡을 수 있습니다.

Ruby (1.9+)가있는 경우

ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file

1
: 당신은 awk END 절에, 당신은 아마 원하는 if (a && b && c) {exit 0} else {exit 1}더 간결 또는exit !(a && b && c)
글렌 잭맨

루비 솔루션이 옳지 않은 것 같습니다. 모든 검색어가 포함 된 단락 만 인쇄합니다. 질문은 : 파일이 (전체적으로) 동일한 단락에 모두 나타나지 않더라도 모든 단어를 포함하고 있습니까?
glenn jackman 2011 년

감사. 전체 파일이 필요한 경우, 다음 -0777를 사용할 필요가 변경
쿠루미

4

여러 파일에서 여러 단어를 검색합니다.

egrep 'abc|xyz' file1 file2 ..filen 

2
두 문자열이 모두있는 파일을 찾는 것 외에도 'abc'또는 'xyz'만있는 파일도 찾습니다. OP가 'abc'와 'xyz'를 포함하는 파일을 요청했다고 생각합니다.
Chris Warth

3

간단히:

grep 'word1\|word2\|word3' *

이 게시물에 대한 추가 정보를 원하시면을


나는 -l깃발 을 추가하고 싶지만 그 외에는 내가 뭔가를 놓치지 않는 한이 대답이 나에게 가장 간단 해 보입니다.
xdhmoore jul.

여러 파이프와 필터 내의 모든 데이터를 처리하지 않기 때문에 그래, 그것은 또한 더 효율적입니다
모세 브 에리

3
이 질문은 세 용어를 모두 포함하는 파일을 반환하는 표현식에 대해 묻습니다. 이것은 세 개 중 하나를 포함하는 행 (파일 이름 대신)을 반환합니다 (세 개 모두 대신).
Benjamin W.

2

이것은 glenn jackman과 kurumi의 답변을 혼합하여 임의의 수의 고정 단어 또는 고정 된 정규식 세트 대신 임의의 수의 정규식을 허용합니다.

#!/usr/bin/awk -f
# by Dennis Williamson - 2011-01-25

BEGIN {
    for (i=ARGC-2; i>=1; i--) {
        patterns[ARGV[i]] = 0;
        delete ARGV[i];
    }
}

{
    for (p in patterns)
        if ($0 ~ p)
            matches[p] = 1
            # print    # the matching line could be printed
}

END {
    for (p in patterns) {
        if (matches[p] != 1)
            exit 1
    }
}

다음과 같이 실행하십시오.

./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat

2

저에게 잘 맞는 것은 다음과 같습니다.

find . -path '*/.svn' -prune -o -type f -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh
./another/path/to/file2.txt
./blah/foo.php

이 세 가지로 .sh 파일을 찾고 싶다면 다음을 사용할 수 있습니다.

find . -path '*/.svn' -prune -o -type f -name "*.sh" -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh

1

@kurumi의 awk 답변을 확장하면 다음과 같은 bash 함수가 있습니다.

all_word_search() {
    gawk '
        BEGIN {
            for (i=ARGC-2; i>=1; i--) {
                search_terms[ARGV[i]] = 0;
                ARGV[i] = ARGV[i+1];
                delete ARGV[i+1];
            }
        }
        {
            for (i=1;i<=NF; i++) 
                if ($i in search_terms) 
                    search_terms[$1] = 1
        }
        END {
            for (word in search_terms) 
                if (search_terms[word] == 0) 
                    exit 1
        }
    ' "$@"
    return $?
}

용법:

if all_word_search Dansk Norsk Svenska filename; then
    echo "all words found"
else
    echo "not all words found"
fi

1

나는 두 단계로 그것을했다. 하나의 파일에 csv 파일 목록 만들기이 페이지 주석의 도움으로 필요한 것을 얻기 위해 스크립트없는 두 단계를 만들었습니다. 터미널에 입력하기 만하면됩니다.

$ find /csv/file/dir -name '*.csv' > csv_list.txt
$ grep -q Svenska `cat csv_list.txt` && grep -q Norsk `cat csv_list.txt` && grep -l Dansk `cat csv_list.txt`

세 단어를 모두 포함하는 파일 이름을 인쇄합니다.

또한 다음과 같은 기호를 염두에 두십시오. `' "


1

두 개의 검색어 만 필요한 경우 가장 읽기 쉬운 방법은 각 검색을 실행하고 결과를 교차하는 것입니다.

 comm -12 <(grep -rl word1 . | sort) <(grep -rl word2 . | sort)

1

git이 설치되어있는 경우

git grep -l --all-match --no-index -e Dansk -e Norsk -e Svenska

--no-index는 Git에서 관리하지 않는 현재 디렉토리의 파일을 검색합니다. 따라서이 명령은 git 저장소인지 여부에 관계없이 모든 디렉토리에서 작동합니다.


0

나는 오늘이 문제가 있었고 여기에있는 모든 한 줄은 파일 이름에 공백이 포함되어 있기 때문에 실패했습니다.

이것이 내가 생각한 것입니다.

grep -ril <WORD1> | sed 's/.*/"&"/' | xargs grep -il <WORD2>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.