답변:
당신이 사용할 수있는 grep 'string1' filename | grep 'string2'
또는, grep 'string1.*string2\|string2.*string1' filename
grep -e "string1" -e "string2"
나는 이것이 당신이 찾고있는 것이라고 생각합니다.
grep -E "string1|string2" filename
나는 다음과 같이 대답한다고 생각합니다.
grep 'string1.*string2\|string2.*string1' filename
둘 중 하나만 존재하거나 둘 다 존재하지 않는 경우에만 일치합니다.
grep -e "string1" -e "string2" filename
같은 행동을 할?
How do I match lines that contains *both* strings?
모든 단어를 포함하는 파일을 임의의 순서로 검색하려면
grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'
첫 번째 grep은 재귀 적 검색 ( r
)을 시작하고 대소 문자 ( i
)를 무시 하고 파일의 어느 곳에서든 l
한 용어 ( 'action'
작은 따옴표)와 일치하는 ( ) 파일 이름을 나열 (인쇄) 합니다.
후속 greps는 다른 용어를 검색하여 대소 문자를 구분하지 않고 일치하는 파일을 나열합니다.
최종 파일 목록은 파일의 임의의 위치에 상관없이 이러한 용어가 포함 된 파일입니다.
grep -ril 'foo' | xargs -d '\n' grep -il 'bar'
당신이있는 경우 grep
로모그래퍼 -P
제한에 대한 옵션 perl
정규식, 당신은 사용할 수 있습니다
grep -P '(?=.*string1)(?=.*string2)'
겹치는 문자열로 작업 할 수 있다는 이점이 있습니다. and를 더 직접 지정할 수 있기 때문에 perl
as를 사용 하는 것이 다소 간단 grep
합니다.
perl -ne 'print if /string1/ && /string2/'
귀하의 방법은 거의 좋았으며 -w 만 누락되었습니다.
grep -w 'string1\|string2' filename
grep -V
.
|
정규 표현식 의 연산자는 또는을 의미합니다. 즉, string1 또는 string2가 일치한다고합니다. 당신은 할 수 있습니다 :
grep 'string1' filename | grep 'string2'
첫 번째 명령의 결과를 두 번째 grep으로 파이프합니다. 그것은 둘 다 일치하는 줄만 줄 것입니다.
grep을 사용하지 말고 대신 awk를 사용하십시오. grep에서 2 개의 정규 표현식 R1 및 R2를 일치 시키려면 다음과 같이 생각하십시오.
grep 'R1.*R2|R2.*R1'
어색한 동안 :
awk '/R1/ && /R2/'
그러나 R2
겹치거나 하위 집합 인 경우 어떻게해야 R1
합니까? grep 명령은 awk 명령과 달리 작동하지 않습니다. 당신이 포함하는 행을 찾으려면 말할 수 있습니다 the
과 heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
이를 위해 2 개의 그렙과 파이프를 사용해야합니다.
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
물론 실제로 분리되도록 요구 한 경우 grep에서 사용한 것과 동일한 정규 표현식을 항상 awk로 작성할 수 있으며 가능한 모든 시퀀스에서 정규 표현식을 반복하지 않는 대체 awk 솔루션이 있습니다.
이를 제쳐두고, 3 개의 정규 표현식 R1, R2 및 R3에 맞게 솔루션을 확장하려면 어떻게해야합니까? grep에서는 다음과 같은 잘못된 선택 중 하나입니다.
grep 'R1.*R2.*R3|R1.*R3.*R2|R2.*R1.*R3|R2.*R3.*R1|R3.*R1.*R2|R3.*R2.*R1' file
grep R1 file | grep R2 | grep R3
어색하지만 간결하고 명백하며 간단하고 효율적입니다.
awk '/R1/ && /R2/ && /R3/'
이제 정규 표현식 R1 및 R2 대신 리터럴 문자열 S1 및 S2를 실제로 일치 시키려면 어떻게해야합니까? grep을 한 번만 호출하면 단순히 grep을 호출 할 수 없습니다. grep을 호출하기 전에 모든 RE 메타 문자를 이스케이프하는 코드를 작성해야합니다.
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
또는 다시 2 개의 그렙과 파이프를 사용하십시오.
grep -F 'S1' file | grep -F 'S2'
awk에서는 regexp 연산자 대신 문자열 연산자를 사용하면됩니다.
awk 'index($0,S1) && index($0.S2)'
이제 한 줄이 아닌 단락에서 2 개의 정규 표현식을 일치 시키려면 어떻게해야합니까? grep, awk에서 사소한 일을 할 수 없습니다 :
awk -v RS='' '/R1/ && /R2/'
전체 파일에서 어떻습니까? awk에서 grep과 trivial로 다시 수행 할 수 없습니다 (이번에는 간결성을 위해 multi-char RS에 GNU awk를 사용하고 있지만 어떤 awk에서 더 많은 코드가 아니거나 제어 문자를 선택할 수는 없습니다) RS가 동일한 작업을 수행하려면 입력에 있어야합니다.
awk -v RS='^$' '/R1/ && /R2/'
따라서 한 줄이나 단락 또는 파일에서 여러 정규 표현식이나 문자열을 찾으려면 grep을 사용하지 말고 awk를 사용하십시오.
awk '/R1/ && /R2/'
대소 문자를 구별는?
awk -v IGNORECASE=1 '/R1/ && /R2/'
어떤 AWK와awk '{x=toupper($0)} x~/R1/ && x~/R2/'
git grep
git grep
여러 패턴과 함께 사용하는 구문은 다음과 같습니다 .
git grep --all-match --no-index -l -e string1 -e string2 -e string3 file
패턴을 , 및 등의 부울 식과 결합 할 수도 있습니다 .--and
--or
--not
확인 man git-grep
도움.
--all-match
여러 패턴 표현식을 제공 할 때이 플래그는 모두 일치하는 행이있는 파일로 일치를 제한하도록 지정됩니다 .
--no-index
Git에서 관리하지 않는 현재 디렉토리에서 파일을 검색하십시오.
-l
/--files-with-matches
/--name-only
파일 이름 만 표시합니다.
-e
다음 매개 변수는 패턴입니다. 기본은 기본 정규 표현식을 사용하는 것입니다.
고려해야 할 다른 매개 변수 :
--threads
사용할 grep worker 스레드 수
-q
/--quiet
/--silent
출력하지 않습니다 일치하는 라인; 일치하는 경우 상태 0으로 종료하십시오.
패턴 유형을 변경하려면 -G
/ --basic-regexp
(기본값), -F
/ --fixed-strings
, -E
/ --extended-regexp
, -P
/를 사용할 수도 있습니다 --perl-regexp
.-f file
및 기타.
관련 :
들어 OR의 작동을 참조하십시오
나는 종종 당신과 같은 문제에 부딪치며 방금 스크립트를 썼습니다.
function m() { # m means 'multi pattern grep'
function _usage() {
echo "usage: COMMAND [-inH] -p<pattern1> -p<pattern2> <filename>"
echo "-i : ignore case"
echo "-n : show line number"
echo "-H : show filename"
echo "-h : show header"
echo "-p : specify pattern"
}
declare -a patterns
# it is important to declare OPTIND as local
local ignorecase_flag filename linum header_flag colon result OPTIND
while getopts "iHhnp:" opt; do
case $opt in
i)
ignorecase_flag=true ;;
H)
filename="FILENAME," ;;
n)
linum="NR," ;;
p)
patterns+=( "$OPTARG" ) ;;
h)
header_flag=true ;;
\?)
_usage
return ;;
esac
done
if [[ -n $filename || -n $linum ]]; then
colon="\":\","
fi
shift $(( $OPTIND - 1 ))
if [[ $ignorecase_flag == true ]]; then
for s in "${patterns[@]}"; do
result+=" && s~/${s,,}/"
done
result=${result# && }
result="{s=tolower(\$0)} $result"
else
for s in "${patterns[@]}"; do
result="$result && /$s/"
done
result=${result# && }
fi
result+=" { print "$filename$linum$colon"\$0 }"
if [[ ! -t 0 ]]; then # pipe case
cat - | awk "${result}"
else
for f in "$@"; do
[[ $header_flag == true ]] && echo "########## $f ##########"
awk "${result}" $f
done
fi
}
용법:
echo "a b c" | m -p A
echo "a b c" | m -i -p A # a b c
원한다면 .bashrc에 넣을 수 있습니다.
두 문자열이 순서대로 정렬되면 on grep
명령 사이에 패턴을 넣습니다 .
$ grep -E "string1(?.*)string2" file
다음 행이 파일에 포함 된 경우의 예 Dockerfile
:
FROM python:3.8 as build-python
FROM python:3.8-slim
: 문자열이 포함 된 행 얻으려면 FROM python
및 as build-python
다음을 사용 :
$ grep -E "FROM python:(?.*) as build-python" Dockerfile
그런 다음 출력에는 두 문자열 이 모두 포함 된 행만 표시됩니다 .
FROM python:3.8 as build-python
ripgrep
다음은 다음을 사용하는 예입니다 rg
.
rg -N '(?P<p1>.*string1.*)(?P<p2>.*string2.*)' file.txt
유한 자동 마타, SIMD 및 공격적인 리터럴 최적화를 사용하여 검색을 매우 빠르게 수행하는 Rust의 정규식 엔진 위에 구축되어 있기 때문에 가장 빠른 그 리핑 도구 중 하나입니다 .
특히 큰 데이터로 작업 할 때 사용하십시오.
GH-875의 관련 기능 요청도 참조하십시오 .
string2
이전에 표시 될 경우를 처리하지 않습니다 string1
. 이 문제에 대한 가장 간단한 해결책은 rg string1 file.txt | rg string2
입니다.