한 줄에서 두 단어를 검색하는 Grep


45

"lemon"과 "rice"라는 단어가있는 줄을 필터링하는 방법을 찾으려고 노력했습니다. 나는 "레몬"이나 "쌀"을 찾는 방법을 알고 있지만 둘은 아닙니다. 그들은 다른 텍스트 옆에있을 필요가 없습니다.


1
파일 내부의 모든 문자열을 찾으려면 FOR 루프에서 grep을 실행할 수 있습니다. unix.stackexchange.com/a/462445/43233
Noam Manos

답변:


61

"같은 줄에 둘 다"는 "쌀"다음에 임의의 문자 다음에 "레몬"또는 다른 방법이 따른다는 것을 의미합니다.

정규식에서 rice.*lemon또는 lemon.*rice입니다. 다음을 사용하여 결합 할 수 있습니다 |.

grep -E 'rice.*lemon|lemon.*rice' some_file

확장 정규 표현식 ( -E) 대신 일반 정규 표현식을 사용 하려면 다음 앞에 백 슬래시가 필요합니다 |.

grep 'rice.*lemon\|lemon.*rice' some_file

조금 더 빨리 길어지고 일반적으로의 여러 호출을 사용하는 것이 더 쉬운 단어는 다음과 grep같습니다.

grep rice some_file | grep lemon | grep chicken

마지막 라인은 없다 연계가 되지 분리 에는? 재치 :이 grep rice포함 된 줄을 찾습니다 rice. grep lemon레몬이 들어있는 라인 만 찾을 수있는 곳으로 공급됩니다 . 뿐만 아니라 이전의 답변 - - 영업 반면 허용하고 있는 [닭 | | 레몬 쌀]의
javadba

스크립트 버전 : askubuntu.com/a/879253/5696
Jeff

@Florian Diesch-왜 |탈출해야 grep하는가? 감사!
도망자

1
@fugitive egrep|OR 논리로 이해되는 확장 정규식을 사용합니다 . grep기본 정규 표현식으로 기본 설정되어 있습니다. 여기서 \|OR
Sergiy Kolodyazhnyy

grep맨 페이지에 명시된 바와 같이 egrep더 이상 사용되지 않으며로 대체되어야합니다 grep -E. 그에 따라 답을 자유롭게 편집 할 수있었습니다.
디저트

26

첫 번째 grep 명령의 출력을 다른 grep 명령으로 파이프하면 두 패턴과 모두 일치합니다. 따라서 다음과 같은 작업을 수행 할 수 있습니다.

grep <first_pattern> <file_name> | grep <second_pattern>

또는,

cat <file_name> | grep <first_pattern> | grep <second_pattern>

예:

파일에 내용을 추가해 봅시다 :

$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt

파일에 포함 된 내용 :

$ cat test_grep.txt 
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.

자, 우리가 원하는 것을 grep합시다 :

$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.

우리는 두 패턴이 일치하는 선만 얻습니다. 이를 확장하고 추가 "AND"일치를 위해 출력을 다른 grep 명령으로 파이프 할 수 있습니다.


21

질문에 'grep'이 필요하지만 간단한 'awk'솔루션을 게시하는 것이 도움이 될 수 있다고 생각했습니다.

awk '/lemon/ && /rice/'

더 많은 단어 나 'and'외에 다른 부울 식으로 쉽게 확장 할 수 있습니다.


11

어떤 순서로 일치를 찾는 또 다른 아이디어는 다음을 사용하는 것입니다.

-P (Perl-Compatibility) 옵션과 긍정적 인 미리보기 정규식을 사용(?=(regex)) 하여 grep :

grep -P '(?=.*?lemon)(?=.*?rice)' infile

또는 대신 아래를 사용할 수 있습니다.

grep -P '(?=.*?rice)(?=.*?lemon)' infile
  • .*?모든 문자와 일치하는 수단이 .사건은 시간을 0 개 이상의 것을 *그들이 패턴 (다음에 선택하는 동안 rice또는 lemon). 는 ?이 (수단이 제로 또는 모든 것을 한 시간이 일치하기 전에 모든 것을 선택한다 .*)

(?=pattern): Positive Lookahead : Positive lookahead 구문은 괄호 쌍으로, 여는 괄호 뒤에 물음표와 등호가옵니다.

모두 포함하여 그래서이 모든 행을 반환 lemon하고 rice임의의 순서로. 또한 이것은 |s와 doubles 를 사용하지 않도록 grep합니다.


외부 링크 : 고급 Grep 주제 Positive Lookahead – 디자이너를위한 GREP


5
grep -e foo -e goo

foo 또는 goo와 일치하는 항목을 반환합니다


1

grep위의 답변과 같은 기반 이 아닌 답변을 제공하는 것이 수용 가능 하다는 것을 인정하면 다음 과 같은 awk간단한 perl줄을 제안합니다 .

$ perl -ne 'print if /lemon/ and /rice/' my_text_file

검색은와 같은 일부 / 모든 단어로 대소 문자를 무시할 수 있습니다 /lemon/i and /rice/i. 어쨌든 대부분의 유닉스 / 리눅스 머신에는 perl이 설치되어 있습니다.


거부 !!! ;) 말이되지 않기 때문에 .. :)
An0n

0

grep 배관 솔루션을 자동화하는 스크립트는 다음과 같습니다.

#!/bin/bash

# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}

grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}

grepand "$@"

1
이것은 아마도 재귀 함수를 사용하는 대신 명령 문자열을 구축하고 구현해야 eval쉽게, 어떤 나누기를 보내고
muru을

@muru 편집을 제안하십시오. 나는 그 의견에 감사한다.
Jeff

1
편집하면 다시 작성하는 것이 너무 많아서 그렇게하지 않습니다. 그것을 추가하고 싶다면 여기에 다음과 같이 보일 것입니다. paste.ubuntu.com/23915379
muru
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.