我正在尝试使用grep
来匹配包含两个不同字符串的行。我尝试过以下操作,但这会匹配包含 string1 或 string2 的行,这不是我想要的。
grep 'string1\|string2' filename
那么我如何只与包含两个字符串的行匹配grep
?
答案 0 :(得分:193)
我认为这就是你要找的东西:
grep -E "string1|string2" filename
我认为答案是这样的:
grep 'string1.*string2\|string2.*string1' filename
仅匹配两者都存在的情况,而不是一个或另一个或两者。
答案 1 :(得分:160)
您可以使用grep 'string1' filename | grep 'string2'
或者,grep 'string1.*string2\|string2.*string1' filename
答案 2 :(得分:45)
只需给它多个-e
选项。
-e pattern, --regexp=pattern
Specify a pattern used during the search of the input: an input
line is selected if it matches any of the specified patterns.
This option is most useful when multiple -e options are used to
specify multiple patterns, or when a pattern begins with a dash
(`-').
因此命令变为:
grep -e "string1" -e "string2" filename
注意:上面我引用了BSD版本的手册,但看起来像是the same on Linux。
答案 3 :(得分:26)
在任何地方搜索包含所有单词的文件:
grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'
第一个grep启动递归搜索(r
),忽略大小写(i
)并列出(打印出)匹配(l
)的文件的名称一个术语('action'
带有单引号)出现在文件的任何位置。
随后的greps搜索其他术语,保留不区分大小写并列出匹配的文件。
您将获得的最终文件列表是包含这些术语的文件,可以按文件中的任何顺序排列。
答案 4 :(得分:14)
如果grep
-P
选项包含有限perl
正则表达式,则可以使用
grep -P '(?=.*string1)(?=.*string2)'
具有处理重叠字符串的优点。使用perl
作为grep
更简单一些,因为您可以更直接地指定和逻辑:
perl -ne 'print if /string1/ && /string2/'
答案 5 :(得分:12)
你的方法差不多,只缺少-w
grep -w 'string1\|string2' filename
答案 6 :(得分:7)
您可以尝试这样的事情:
(pattern1.*pattern2|pattern2.*pattern1)
答案 7 :(得分:5)
正则表达式中的|
运算符表示或。也就是说string1或string2匹配。你可以这样做:
grep 'string1' filename | grep 'string2'
将第一个命令的结果传递给第二个grep。这应该只给你两条线。
答案 8 :(得分:3)
正如人们建议使用perl和python以及复杂的shell脚本,这里有一个简单的 awk 方法:
awk '/string1/ && /string2/' filename
对已接受的答案进行了评论:不,这不做多行;但那也不是问题的作者所要求的。
答案 9 :(得分:2)
找到仅以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
答案 10 :(得分:2)
假设我们需要在文件测试文件中找到多个单词的计数。 有两种方法可以解决这个问题
1)使用带正则表达式匹配模式的grep命令
grep -c '\<\(DOG\|CAT\)\>' testfile
2)使用egrep命令
egrep -c 'DOG|CAT' testfile
使用egrep,您无需担心表达式,只需通过管道分隔符分隔单词。
答案 11 :(得分:1)
将要grep的字符串放入文件
echo who > find.txt
echo Roger >> find.txt
echo [44][0-9]{9,} >> find.txt
然后使用-f
进行搜索grep -f find.txt BIG_FILE_TO_SEARCH.txt
答案 12 :(得分:1)
grep '(string1.*string2 | string2.*string1)' filename
将以任何顺序获取string1和string2的行
答案 13 :(得分:1)
grep -i -w 'string1\|string2' filename
这适用于精确的单词匹配和匹配不区分大小写的单词,因为使用了-i
答案 14 :(得分:1)
grep ‘string1\|string2’ FILENAME
GNU grep版本3.1
答案 15 :(得分:0)
我经常遇到和你一样的问题,我刚写了一段脚本:
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中。
答案 16 :(得分:0)
用于多行匹配:
echo -e "test1\ntest2\ntest3" |tr -d '\n' |grep "test1.*test3"
或
echo -e "test1\ntest5\ntest3" >tst.txt
cat tst.txt |tr -d '\n' |grep "test1.*test3\|test3.*test1"
我们只需要删除换行符就行了!
答案 17 :(得分:0)
你应该grep
这样:
$ grep 'string1' file | grep 'string2'
答案 18 :(得分:0)
请勿尝试使用grep,而应使用awk。要在grep中匹配2个正则表达式R1和R2,您会认为它是:
grep 'R1.*R2|R2.*R1'
在awk中会是:
awk '/R1/ && /R2/'
但是如果R2
与R1
重叠或为the
的子集怎么办?该grep命令根本无法工作,而awk命令却可以。假设您要查找包含heat
和$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
的行:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
您必须为此使用2个抓钩和一个管道:
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
当然,如果您实际上需要将它们分开,则可以始终使用与grep中所用的相同的正则表达式编写awk,并且有一些替代性的awk解决方案,它们不涉及在所有可能的顺序中重复该正则表达式。 >
放在一边,如果您想扩展您的解决方案以匹配3个正则表达式R1,R2和R3,该怎么办。在grep中,这将是这些不佳的选择之一:
awk '/R1/ && /R2/ && /R3/'
awk简洁明了,简单,有效:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
现在,如果您实际上想匹配文字字符串S1和S2而不是正则表达式R1和R2,该怎么办?您根本无法在一次调用grep中做到这一点,您必须在调用grep之前编写代码以转义所有RE元字符:
grep -F 'S1' file | grep -F 'S2'
或再次使用2个抓钩和一根烟斗:
awk 'index($0,S1) && index($0.S2)'
这仍然是较差的选择,而使用awk时,您仅使用字符串运算符而不是regexp运算符:
awk -v RS='' '/R1/ && /R2/'
现在,如果要在段落而不是一行中匹配2个正则表达式怎么办?无法在grep中完成,在awk中则微不足道:
awk -v RS='^$' '/R1/ && /R2/'
整个文件怎么样?再次无法在grep和awk中实现微不足道(这一次,我为简洁起见将GNU awk用于多字符RS,但是在任何awk中代码都不多,或者您可以选择一个您不会知道的控制字符可以在RS的输入中进行相同的操作):
public class Practice {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
ob1.t.start();
ob2.t.start();
try {
Thread.sleep(1000);
} catch(InterruptedException a) {
System.out.println("Exception a caught");
}
}
}
所以-如果您要在一行,段落或文件中找到多个正则表达式或字符串,则不要使用grep,请使用awk。
答案 19 :(得分:0)
git grep
以下是使用git grep
的多种模式的语法:
git grep --all-match --no-index -l -e string1 -e string2 -e string3 file
您还可以将模式与 Boolean 表达式结合使用,例如--and
,--or
和--not
。
检查man git-grep
以获得帮助。
--all-match
在提供多个模式表达式时,指定此标志以将匹配项限制为具有所有行都匹配的文件。
--no-index
在当前目录中搜索不受Git管理的文件。
-l
/--files-with-matches
/--name-only
仅显示文件名。
-e
下一个参数是图案。默认是使用基本的正则表达式。
要考虑的其他参数:
--threads
要使用的grep工作线程数。
-q
/--quiet
/--silent
不输出匹配的行;匹配时退出,状态为0。
要更改图案类型,您还可以使用-G
/ --basic-regexp
(默认),-F
/ --fixed-strings
,-E
/ {{1} },--extended-regexp
/ -P
,--perl-regexp
等。
相关:
有关 OR 操作,请参见:
答案 20 :(得分:0)
两个字符串都按顺序排列时,请在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
答案 21 :(得分:-1)
ripgrep
以下是使用rg
的示例:
rg -N '(?P<p1>.*string1.*)(?P<p2>.*string2.*)' file.txt
它是最快的grepping工具之一,因为它建立在Rust's regex engine之上,它使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。
使用它,尤其是在处理大数据时。
另请参见GH-875上的相关功能请求。