Answers:
您可以使用 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'
与出现在文件中任何位置的带单引号)相同。
后续的搜索将搜索其他术语,以保持不区分大小写并列出匹配的文件。
您将获得的文件的最终列表将是包含这些术语的文件,其顺序为文件中任何位置。
grep -ril 'foo' | xargs -d '\n' grep -il 'bar'
如果您有一个针对正则表达式grep
的-P
选项,perl
则可以使用
grep -P '(?=.*string1)(?=.*string2)'
这具有使用重叠字符串的优势。使用perl
as会更直接一些grep
,因为您可以更直接地指定and逻辑:
perl -ne 'print if /string1/ && /string2/'
您的方法几乎不错,只缺少-w
grep -w 'string1\|string2' filename
grep -V
是什么。
grep -w 'regexp1\|regexp2' filename
|
正则表达式中的运算符表示或。也就是说,string1或string2将匹配。您可以这样做:
grep 'string1' filename | grep 'string2'
这会将第一个命令的结果通过管道传递给第二个grep。那只会给您同时匹配的行。
不要尝试为此使用grep,而应使用awk。要在grep中匹配2个正则表达式R1和R2,您会认为是:
grep 'R1.*R2|R2.*R1'
而在awk中它将是:
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中所用的相同的regexp来用awk编写,并且有一些替代性的awk解决方案,它们不涉及在所有可能的顺序中重复该regexp。
抛开这些,如果您想扩展您的解决方案以匹配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中,它将是简洁,明显,简单,有效的:
awk '/R1/ && /R2/ && /R3/'
现在,如果您实际上想匹配文字字符串S1和S2而不是正则表达式R1和R2,该怎么办?您根本无法在一次调用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/'
整个文件怎么样?再次无法在grep和awk中实现微不足道(这一次,为了简洁起见,我将GNU awk用于多字符RS,但是在任何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
下一个参数是模式。默认是使用基本的regexp。
要考虑的其他参数:
--threads
要使用的grep工作线程数。
-q
/--quiet
/--silent
不匹配的输出线; 匹配时以状态0退出。
要更改图案类型,您还可以使用-G
/ --basic-regexp
(默认),-F
/ --fixed-strings
,-E
/ --extended-regexp
,-P
/ --perl-regexp
,-f file
和其他。
有关:
有关“ 或”运算,请参见:
将您要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
我经常遇到与您相同的问题,我只是写了一段脚本:
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
它是最快的grepping工具之一,因为它基于Rust的regex引擎构建该使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。
使用它,尤其是在处理大数据时。
另请参阅GH-875上的相关功能要求。
string2
出现在之前时不会处理这种情况string1
。解决此问题的最简单方法是rg string1 file.txt | rg string2
。