grep은 검색 패턴과 일치하는 단어 만 표시 할 수 있습니까?


685

검색 표현식과 일치하는 파일에서 grep 출력을 "단어"로 만드는 방법이 있습니까?

여러 파일에서 "th"와 같은 모든 인스턴스를 찾으려면 다음을 수행 할 수 있습니다.

grep "th" *

그러나 출력은 다음과 같습니다 (굵게 나타납니다).

일부 텍스트 파일은 : 고양이에 앉아 매트  
일부-다른 텍스트 파일 : 빠른 갈색 여우  
아직 다른 텍스트 파일 : 나는 희망  그것을 설명 철저 

동일한 검색을 사용하여 출력하고 싶은 것은 다음과 같습니다.

the
the
the
this
thoroughly

grep을 사용하여 가능합니까? 아니면 다른 도구 조합을 사용합니까?


2
Dan Midwood 솔루션은 완벽하게 작동하며 크레딧을받을 가치가 있습니다.
hakish 2016 년

줄을 바꾸지 않고 일치하는 단어를 인쇄 할 수있는 방법이 있습니까? 일치하는 문자열이 같은 줄에 남아 있어야합니까?
Linguist

답변:


956

grep -o를 사용해보십시오

grep -oh "\w*th\w*" *

편집 : Phil의 의견과 일치

에서 워드 프로세서 :

-h, --no-filename
    Suppress the prefixing of file names on output. This is the default
    when there is only  one  file  (or only standard input) to search.
-o, --only-matching
    Print  only  the matched (non-empty) parts of a matching line,
    with each such part on a separate output line.

9
@ user181548, grep -o 옵션은 GNU grep에서만 작동합니다. 따라서 GNU grep을 사용하지 않으면 작동하지 않을 수 있습니다.
ksinkar

5
@ABB 일치하는 파일의 이름을 표시할지 여부에 따라 다릅니다. 어떤 조건 하에서 표시되는지 표시되지 않는지 확실하지 않지만 여러 디렉토리에서 grep을 사용하면 일치하는 모든 파일의 전체 파일 경로가 표시되지만 -h를 사용하면 어떤 파일인지에 대한 사양이없는 일치하는 단어. 따라서 원래 질문과 일치시키기 위해 특정 상황에서는 필요하다고 생각합니다.
LokMac 1

1
무슨 "\w*th\w*" *의미 인지 설명해야 했기 때문에 게시하겠다고 생각했습니다. \w는 [_ [: alnum :]]이므로 기본적으로 'th'가 포함 된 "word"( \w공백이 포함되지 않기 때문에)와 일치 합니다. 인용 된 섹션 뒤의 *는 어떤 파일에 대한 glob입니다 (즉,이 디렉토리의 모든 파일과 일치)
jeremysprofile

1
\w일반적으로 휴대가 쉽지 않다 grep -E; 적절한 이식성을 위해 POSIX 문자 클래스 이름을 [[:alnum:]]대신 사용하십시오 (또는 [_[:alnum:]]실제로 밑줄을 원하거나 grep -P플랫폼에 해당 이름이 있는지 시도 하십시오).
tripleee

@ABB OP에 의해 보여지는 원하는 출력을 감안할 때, -h전적으로 필요한 것입니다 ..?
El Ronnoco

81

교차 배포 안전 답변 (Windows minGW 포함)

grep -h "[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '\n' | grep -h "[[:alpha:]]*th[[:alpha:]]*"

-o 옵션을 포함하지 않는 이전 버전의 grep (예 : 2.4.2)을 사용하는 경우 위를 사용하십시오. 그렇지 않으면 더 간단한 버전을 유지하십시오.

리눅스 교차 배포 안전 답변

grep -oh "[[:alpha:]]*th[[:alpha:]]*" 'filename'

-oh출력 을 요약 하면 정규 표현식이 vim / etc에서 작동하는 방식과 마찬가지로 파일 이름이 아닌 파일 내용과 일치하는 정규 표현식이 검색됩니다. 당신! 펄 구문이 아닌 POSIX를 유지하는 한 (아래 참조)

grep 매뉴얼에서 더보기

-o      Print each match, but only the match, not the entire line.
-h      Never print filename headers (i.e. filenames) with output lines.
-w      The expression is searched for as a word (as if surrounded by
         `[[:<:]]' and `[[:>:]]';

원래 답변이 모든 사람에게 적용되지 않는 이유

\w확장 된 "perl"구문으로 사용법은 플랫폼마다 다릅니다. 따라서 POSIX 문자 클래스와 함께 작동하도록 제한되는 grep 설치 [[:alpha:]]는 펄에 해당하지 않습니다 \w. 자세한 내용은 정규식 Wikipedia 페이지를 참조하십시오.

궁극적으로 위의 POSIX 답변은 grep 플랫폼 (원본)에 관계없이 훨씬 안정적입니다.

-o 옵션없이 grep을 지원하는 경우 첫 번째 grep은 관련 행을 출력하고 tr은 공백을 새 행으로 분할하고 최종 grep은 해당 행에 대해서만 필터링합니다.

(PS : 지금까지 대부분의 플랫폼을 알고 있으며 \ w ...에 대해 패치되었을 것입니다.

@AdamRosenfield 답변의 "-o"해결 방법에 대한 크레딧


1
-o는 GNU grep에서만 작동하는 것은 어떻습니까?
Brilliand

@ Brilliand 흠, '-o'를 지원하지 않는 리눅스 구현을 찾는 데 어려움을 겪고 있습니다. 어떤 플랫폼을 검사 해야하는지 알면 해결 방법을 찾을 수 있습니다.
PicoCreator

@pico -ogit 패키지 (minGW?)와 함께 설치되는 Windows grep에는 이 옵션이 없습니다. "c:\Program Files (x86)\Git\bin\grep" --version grep (GNU grep) 2.4.2
Bruce Peterson

@BrucePeterson -o에 대한 AdamRosenfield 해결 방법 답변에 추가했습니다 .Windows git에 tr / sed 및 해당 버전이 포함되어 있는지 확인하십시오. 따라서이 해결 방법이 작동하는지 확인할 수 있습니다
PicoCreator

@pico : GIT 용 : GNU sed 버전 4.2.1, tr (GNU textutils) 2.0
Bruce Peterson

46

생각보다 간단합니다. 이 시도:

egrep -wo 'th.[a-z]*' filename.txt #### (Case Sensitive)

egrep -iwo 'th.[a-z]*' filename.txt  ### (Case Insensitive)

어디,

 egrep: Grep will work with extended regular expression.
 w    : Matches only word/words instead of substring.
 o    : Display only matched pattern instead of whole line.
 i    : If u want to ignore case sensitivity.

2
이것은 4 년 전의 기존 답변보다 아무것도 추가하지 않는 것 같습니다.
tripleee

3
@tripleee 내 접근 방식이 더 좋고 간단하다는 것을 알았으므로 게시했습니다.
Abhinandan prasad

42

다음과 같이 공백을 개행으로 변환 한 다음 grep 할 수 있습니다.

cat * | tr ' ' '\n' | grep th

18
고양이가 필요 없습니다. tr '' '\ n'<파일 | grep th. 큰 파일의 경우 속도가 느립니다.
ghostdog74 2009

이 작동하지 않았다. 출력에는 여전히 파일 이름과 일치하는 파일의 전체 줄이 포함되어 있습니다. 어쨌든, 제공된 다른 솔루션 중 하나가 효과가있었습니다. 그래도 입력 주셔서 감사합니다.
Neil Baldwin

@ ghostdog74 : 좋은 지적이지만 파일 이상을 가지고 있다면 고양이를 사용해야합니다. @Neil Baldwin : 정확히 입력 했습니까? 입력 파일이 하나만 있으면 (이 경우 stdin) grep은 파일 이름을 인쇄하지 않습니다.
Adam Rosenfield

@ 아담-예, 죄송합니다 아담, 하나의 파일로 작동하지만 여러 파일로 작동하지 않습니다.
Neil Baldwin 09.

4
@ ghostdog74 느린 부분 때문에 인 경우 tr자신이 할 수있는, grep그래서 처음 tr에만 일치하는 라인에 적용 할 것입니다 :grep th filename | tr ' ' '\n' | grep th
Carcamano

37

단지 awk도구 조합이 필요하지 않습니다.

# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly

8
@AjeetGanga 글쎄, 그것은 이름입니다
Daerdemandt

11

일치 및 perl 전용 grep 명령

grep -o -P 'th.*? ' filename

3
일치하는 그룹 만 표시하는 것은 어떻습니까?
Bishwas Mishra

작동하지 않습니다. th와일드 카드의 가장 짧은 반복을 요청했기 때문에 찾을 수 있습니다.
tripleee

@tripleee-정규식 끝에 공백이 포함되어 있기 때문에 문제가 없습니다. 그러나 그 뒤에 공백이없는 단어 (예 : 줄 끝)가 누락됩니다.
Ken Williams

8

나는 awk의 구문을 기억하기 어려운 것에 만족하지 않았지만 이것을 수행하기 위해 하나의 유틸리티를 사용하는 아이디어를 좋아했다.

ack (또는 Ubuntu를 사용하는 경우 ack-grep)이 쉽게 할 수있는 것처럼 보입니다.

# ack-grep -ho "\bth.*?\b" *

the
the
the
this
thoroughly

-h 플래그를 생략하면 다음과 같은 결과가 나타납니다.

# ack-grep -o "\bth.*?\b" *

some-other-text-file
1:the

some-text-file
1:the
the

yet-another-text-file
1:this
thoroughly

보너스로, --output플래그를 사용하여 내가 찾은 가장 쉬운 구문으로 더 복잡한 검색을 수행 할 수 있습니다 .

# echo "bug: 1, id: 5, time: 12/27/2010" > test-file
# ack-grep -ho "bug: (\d*), id: (\d*), time: (.*)" --output '$1, $2, $3' test-file

1, 5, 12/27/2010


4

"icon-"으로 시작하여 모든 단어를 검색하려면 다음 명령이 완벽하게 작동합니다. grep과 비슷하지만 더 나은 옵션과 멋진 형식으로 Ack를 사용 하고 있습니다.

ack -oh --type=html "\w*icon-\w*" | sort | uniq

3

pcregrep 을 시도 할 수도 있습니다 . grep 에도 -w옵션이 있지만 경우에 따라 예상대로 작동하지 않습니다.

에서 위키 백과 :

cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple

3

grep / pattern regex와 "matched pattern found"를 출력으로 찾는 것과 비슷한 문제가있었습니다.

결국 나는 egrep 옵션을 사용하여 egrep (grep -e 또는 -G의 동일한 정규 표현식이 egrep의 동일한 결과를 얻지 못했습니다)을 사용했습니다

그래서, 나는 (나는 정규식 마스터가 아닙니다)와 비슷한 것이라고 생각합니다.

egrep -o "the*|this{1}|thoroughly{1}" filename

쓸모없는 {1}수량자를 삭제해야합니다. 또는 당신은 일관되게, 원하는 경우 t{1}h{1}e{1}
tripleee을

같은 줄로 인쇄 할 수 있습니까?
吴毅 凡

-1

다음과 같이 grep 출력을 Perl에 파이프 할 수 있습니다.

grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'

9
올바른 결과를 얻지 못합니다. 또한 Perl을 사용하는 경우 grep을 사용할 필요가 없습니다. 펄에서 모든 것을하십시오.
ghostdog74 2009

ghostdog74 오류를 지적 해 주셔서 감사합니다. 나는 첫 번째 단어뿐만 아니라 모든 단어를 인쇄하도록 변경했습니다.

내가 말했듯이, grep은 필요하지 않습니다. perl -n -e'while (/ (\ s + th \ w *) / g) {print "$ 1 \ n"} '파일
ghostdog74

7
당신에게 달려 있습니다. 나는 단지 요점을 보여주고있다. 필요하지 않으면하지 마십시오. 그 여분의 "|" 하나의 프로세스에 더 많은 비용이 듭니다.
ghostdog74 2009

1
Perl 5.10 이상에서 : perl -nE '@a = / (regexp) / ig; "\ n", @a '가입
Photon 교수 Photon

-1
$ grep -w

grep 매뉴얼 페이지에서 발췌 :

-w : 전체 단어를 구성하는 일치 항목이 포함 된 행만 선택하십시오. 테스트는 일치하는 부분 문자열이 줄의 시작 부분에 있거나 단어가 아닌 구성 문자 앞에 와야합니다.


1
여전히 일치하는 내용을 포함하는 전체 줄을 인쇄합니다. the예를 들어 "these"또는 "bathe"와 더 이상 일치하지 않도록 실제 일치를 제한합니다 .
tripleee

-6

ripgrep

다음은 다음을 사용하는 예입니다 ripgrep.

rg -o "(\w+)?th(\w+)?"

일치하는 모든 단어와 일치 th합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.