grep으로 한 줄에 두 줄을 일치시킵니다.
grep
두 개의 다른 문자열이 포함 된 줄을 일치시키는 데 사용하려고합니다 . 나는 다음을 시도했지만 이것은 내가 원하는 것이 아닌 string1 또는 string2 를 포함하는 줄과 일치합니다 .
grep 'string1\|string2' filename
그렇다면 두 문자열을 모두grep
포함하는 줄만 어떻게 일치 합니까?
당신이 사용할 수있는 grep 'string1' filename | grep 'string2'
또는, grep 'string1.*string2\|string2.*string1' filename
나는 이것이 당신이 찾고있는 것이라고 생각합니다.
grep -E "string1|string2" filename
나는 다음과 같이 대답한다고 생각합니다.
grep 'string1.*string2\|string2.*string1' filename
둘 중 하나만 존재하거나 둘 다 존재하지 않는 경우에만 일치합니다.
모든 단어를 포함하는 파일을 임의의 순서로 검색하려면
grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'
첫 번째 grep은 재귀 적 검색 ( r
)을 시작하고 대소 문자 ( i
)를 무시 하고 파일의 어느 곳에서든 l
한 용어 ( 'action'
작은 따옴표)와 일치하는 ( ) 파일 이름을 나열 (인쇄) 합니다.
후속 greps는 다른 용어를 검색하여 대소 문자를 구분하지 않고 일치하는 파일을 나열합니다.
귀하가 받게 될 최종 파일 목록은 파일의 임의의 위치에 상관없이 이러한 용어를 포함하는 것들입니다.
당신이있는 경우 grep
로모그래퍼 -P
제한에 대한 옵션 perl
정규식, 당신은 사용할 수 있습니다
grep -P '(?=.*string1)(?=.*string2)'
겹치는 문자열로 작업 할 수 있다는 이점이 있습니다. and를 더 직접 지정할 수 있기 때문에 perl
as를 사용 하는 것이 다소 간단 grep
합니다.
perl -ne 'print if /string1/ && /string2/'
귀하의 방법은 거의 좋았으며 -w 만 누락되었습니다.
grep -w 'string1\|string2' filename
|
정규 표현식 의 연산자는 또는을 의미합니다. 즉, string1 또는 string2가 일치한다고합니다. 당신은 할 수 있습니다 :
grep 'string1' filename | grep 'string2'
첫 번째 명령의 결과를 두 번째 grep으로 파이프합니다. 그것은 둘 다 일치하는 줄만 줄 것입니다.
다음과 같이 시도해보십시오.
(pattern1.*pattern2|pattern2.*pattern1)
사람들이 펄과 파이썬, 복잡한 셸 스크립트를 제안한 것처럼 간단한 awk 접근법이 있습니다.
awk '/string1/ && /string2/' filename
허용 된 답변에 대한 의견을 살펴본 결과 : 아니요, 여러 줄로 수행되지 않습니다. 그러나 그것은 또한 그 질문의 저자가 요구 한 것이 아닙니다.
6 개의 공백으로 시작하고 다음으로 끝나는 행을 찾았습니다.
cat my_file.txt | grep
-e '^ .*(\.c$|\.cpp$|\.h$|\.log$|\.out$)' # .c or .cpp or .h or .log or .out
-e '^ .*[0-9]\{5,9\}$' # numers between 5 and 9 digist
> nolog.txt
파일 테스트 파일에서 여러 단어 수를 찾아야한다고 가정 해 봅시다. 그것에 대해 두 가지 방법이 있습니다
1) 정규식 일치 패턴과 함께 grep 명령을 사용하십시오.
grep -c '\<\(DOG\|CAT\)\>' testfile
2) egrep 명령 사용
egrep -c 'DOG|CAT' testfile
egrep을 사용하면 표현에 대해 걱정할 필요가 없으며 파이프 구분 기호로 단어를 구분하면됩니다.
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/'
How about across a whole file? Again can't be done in grep and trivial in awk (this time I'm using GNU awk for multi-char RS for conciseness but it's not much more code in any awk or you can pick a control-char you know won't be in the input for the RS to do the same):
awk -v RS='^$' '/R1/ && /R2/'
So - if you want to find multiple regexps or strings in a line or paragraph or file then don't use grep, use awk.
grep ‘string1\|string2’ FILENAME
GNU grep version 3.1
Place the strings you want to grep for into a file
echo who > find.txt
echo Roger >> find.txt
echo [44][0-9]{9,} >> find.txt
Then search using -f
grep -f find.txt BIG_FILE_TO_SEARCH.txt
grep '(string1.*string2 | string2.*string1)' filename
will get line with string1 and string2 in any order
grep -i -w 'string1\|string2' filename
This works for exact word match and matching case insensitive words ,for that -i is used
git grep
Here is the syntax using git grep
with multiple patterns:
git grep --all-match --no-index -l -e string1 -e string2 -e string3 file
You may also combine patterns with Boolean expressions such as --and
, --or
and --not
.
Check man git-grep
for help.
--all-match
When giving multiple pattern expressions, this flag is specified to limit the match to files that have lines to match all of them.
--no-index
Search files in the current directory that is not managed by Git.
-l
/--files-with-matches
/--name-only
Show only the names of files.
-e
The next parameter is the pattern. Default is to use basic regexp.
Other params to consider:
--threads
Number of grep worker threads to use.
-q
/--quiet
/--silent
Do not output matched lines; exit with status 0 when there is a match.
To change the pattern type, you may also use -G
/--basic-regexp
(default), -F
/--fixed-strings
, -E
/--extended-regexp
, -P
/--perl-regexp
, -f file
, and other.
Related:
- How to grep for two words existing on the same line?
- Check if all of multiple strings or regexes exist in a file
- How to run grep with multiple AND patterns? & Match all patterns from file at once
For OR operation, see:
- How do I grep for multiple patterns with pattern having a pipe character?
- Grep: how to add an “OR” condition?
for multiline match:
echo -e "test1\ntest2\ntest3" |tr -d '\n' |grep "test1.*test3"
or
echo -e "test1\ntest5\ntest3" >tst.txt
cat tst.txt |tr -d '\n' |grep "test1.*test3\|test3.*test1"
we just need to remove the newline character and it works!
You should have grep
like this:
$ grep 'string1' file | grep 'string2'
I often run into the same problem as yours, and I just wrote a piece of script:
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
}
Usage:
echo "a b c" | m -p A
echo "a b c" | m -i -p A # a b c
You can put it in .bashrc if you like.
ripgrep
Here is the example using rg
:
rg -N '(?P<p1>.*string1.*)(?P<p2>.*string2.*)' file.txt
It's one of the quickest grepping tools, since it's built on top of Rust's regex engine which uses finite automata, SIMD and aggressive literal optimizations to make searching very fast.
Use it, especially when you're working with a large data.
See also related feature request at GH-875.
참고URL : https://stackoverflow.com/questions/4487328/match-two-strings-in-one-line-with-grep
'IT story' 카테고리의 다른 글
Cocoa 앱에서 터미널 명령 실행 (0) | 2020.05.08 |
---|---|
자바 연관 배열 (0) | 2020.05.08 |
데이터 프레임에서 행을 어떻게 삭제합니까? (0) | 2020.05.08 |
1030 저장소 엔진에서 28 오류가 발생했습니다 (0) | 2020.05.08 |
오류 ITMS-9000 :“중복 이진 업로드. (0) | 2020.05.08 |