grep pattern1 | grep pattern2 | ...
那么如何将其转换为类似我想使用单个grep,因为我是动态构建参数的,因此所有内容都必须放在一个字符串中。使用filter是系统功能,而不是grep,因此不是系统功能。
不要将此问题与以下内容混淆:
grep pattern1 & pattern2 & pattern3
这是一个或多模式匹配。
#1 楼
agrep
可以使用以下语法来做到这一点:agrep 'pattern1;pattern2'
使用GNU
grep
,当构建有PCRE支持时,您可以执行以下操作:grep -P '^(?=.*pattern1)(?=.*pattern2)'
使用ast
grep
:grep -X '.*pattern1.*&.*pattern2.*'
(将
.*
添加为<x>&<y>
会匹配完全匹配<x>
和<y>
的字符串,而a&b
将永远不会匹配,因为没有这样的字符串可以同时为a
和b
。)如果模式不重叠,则还可以:
grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
最好的便携式方法可能是已经提到的
awk
:awk '/pattern1/ && /pattern2/'
sed
:sed -e '/pattern1/!d' -e '/pattern2/!d'
请注意,所有这些都将具有不同的正则表达式语法。
评论
agrep语法不适用于我...它引入了哪个版本?
–拉曼
2016年9月5日在22:15
1992年的@Raman 2.04已经有了它。我没有理由相信它从一开始就不存在。可以在glimpse / webglimpse中找到较新的(1992年之后)agrep版本。可能您有不同的实现。我对于ast-grep版本有一个错误,增强正则表达式的选项是-X,而不是-A。
–StéphaneChazelas
16-09-6在5:55
@StéphaneChazelas谢谢,我在Fedora 23上有agrep 0.8.0。这似乎是与您引用的agrep不同的agrep。
–拉曼
2016年9月6日下午6:37
@Raman,您的声音听起来像TRE agrep。
–StéphaneChazelas
2016年9月6日7:01
@Techiee,或者只是awk'/ p1 / && / p2 / {n ++}; END {打印0 + n}'
–StéphaneChazelas
17年6月28日在20:23
#2 楼
您未指定grep版本,这一点很重要。一些正则表达式引擎允许使用“&”按AND将多个匹配分组,但这是非标准且不可移植的功能。但是,至少GNU grep不支持此功能。您可以简单地用sed,awk,perl等替换grep(按重量增加的顺序列出)。使用awk时,命令看起来像
awk '/regexp1/ && /regexp2/ && /regexp3/ { print; }'
,并且可以轻松地在命令行中指定它。
评论
请记住,awk使用ERE,例如等同于grep -E,而不是普通grep使用的BRE。
– jw013
2012年10月10日9:42
awk的正则表达式称为ERE,但实际上它们有点特质。这里可能是比任何人都关心的更多细节:wiki.alpinelinux.org/wiki/Regex
– dubiousjim
2012年11月10日15:35
谢谢grep 2.7.3(openSUSE)。我投票给您,但我将让问题待一会儿,也许grep有一些窍门(不是我不喜欢awk,只是知道更多更好)。
–greenoldman
2012年11月10日15:42
默认操作是打印匹配的行,因此{print; }部分在这里并不是真正必要或有用的。
–tripleee
17-4-20在11:58
#3 楼
如果patterns
每行包含一个模式,则可以执行以下操作: awk 'NR==FNR{a[awk 'NR==FNR{a[patterns
];next}{for(i in a)if(!index(NR==FNR
,i))next}1' patterns -
];next}{for(i in a)if(FILENAME==ARGV[1]
!~i)next}1' patterns -
或它匹配子字符串而不是正则表达式:
ARGIND==1
要打印所有而不是没有行如果
gawk
为空,则输入,用ga
或gai
中的ga(){ awk 'FILENAME==ARGV[1]{a[q4312079q];next}{for(i in a)if(!index(q4312079q,i))next}1' <(printf %s\n "$@") -; }
gai(){ awk 'FILENAME==ARGV[1]{a[tolower(q4312079q)];next}{for(i in a)if(!index(tolower(q4312079q),i))next}1' <(printf %s\n "$@") -; }
替换q4312079q。这些函数打印STDIN的行,其中包含指定为参数的每个字符串作为子字符串的STDIN行。 q4312079q代表grep all,而q4312079q忽略大小写。q4312079q
评论
明确的答案,解决了几种用例和工作原理(在macOS上验证)
– ShpielMeister
20年8月8日在18:19
#4 楼
grep pattern1 | grep pattern2 | ...
我想使用单个grep,因为我正在动态地构建参数,因此所有内容都必须放在一个字符串中。
实际上可以动态地构建管道(无需采取任何措施)到
eval
): # Executes: grep "" | grep "" | grep "" | ...
function chained-grep {
local pattern=""
if [[ -z "$pattern" ]]; then
cat
return
fi
shift
grep -- "$pattern" | chained-grep "$@"
}
cat something | chained-grep all patterns must match order but matter dont
这可能不是一个非常有效的解决方案。
评论
使用chained-grep()或函数chained-grep,但不要使用函数chained-grep():unix.stackexchange.com/questions/73750/…
– nisetama
19年1月19日在17:08
您能描述一下窍门吗?您可以通过编辑将其添加到答案中(不带“编辑:”,“更新:”或类似内容)吗?
– Peter Mortensen
20-10-30在20:40
重新设计了答案,使技巧更清晰(即:动态构建外壳管道)
–olejorgenb
20-10-30在23:21
#5 楼
git grep
使用
git grep
的语法是使用布尔表达式组合多个模式:git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3
以上命令将在以下位置打印与所有模式匹配的行
--no-index
在当前目录中搜索不受Git管理的文件。检查
man git-grep
以获得帮助。另请参阅:
如何使用grep匹配string1和string2?
检查文件中是否存在所有多个字符串或正则表达式。 br />
有关“或”运算的信息,请参见:
如何对带有管道字符的图案的多个图案进行grep?
Grep:如何添加“ OR”条件?
评论
极好的答案。谢谢。
–穆罕默德·巴纳(Mohamed Bana)
20-10-6在9:22
#6 楼
这是我的看法,适用于多行单词:使用
find . -type f
,后跟尽可能多的-exec grep -q 'first_word' {} \;
,最后一个带有
-exec grep -l 'nth_word' {} \;
的关键字-q
安静/无声-l
显示具有匹配项的文件以下返回其中包含单词“ rabbit”和“ hole”的文件名列表:
find . -type f -exec grep -q 'rabbit' {} \; -exec grep -l 'hole' {} \;
评论
如果仔细看,您可能会发现这不是问题所要求的功能。
– G-Man说“恢复莫妮卡”
20 Dec 7'在5:40
#7 楼
ripgrep
下面是使用
rg
的示例:rg -N '(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)' file.txt
它是最快的grepping工具之一,因为它是基于Rust的正则表达式引擎构建的它使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。
另请参阅GH-875上的相关功能要求。
#8 楼
要查找所有单词(或模式),可以在grep
循环中运行for
。这里的主要优点是从正则表达式列表中搜索。一个真实的示例:
# File 'search_all_regex_and_error_if_missing.sh'
find_list="\
^a+$ \
^b+$ \
^h+$ \
^d+$ \
"
for item in $find_list; do
if grep -E "$item" file_to_search_within.txt
then
echo "$item found in file."
else
echo "Error: $item not found in file. Exiting!"
exit 1
fi
done
现在让我们在此文件上运行它:
hhhhhhhhhh
aaaaaaa
bbbbbbbbb
ababbabaabbaaa
ccccccc
dsfsdf
bbbb
cccdd
aa
caa
$ ./search_all_regex_and_error_if_missing.sh
aaaaaaa aa
^a+$ found in file.
bbbbbbbbb bbbb
^b+$ found in file.
hhhhhhhhhh
^h+$ found in file.
Error: ^d+$ not found in file. Exiting!
评论
您的逻辑有误-我要求使用ALL运算符,您的代码用作OR运算符,而不是AND。顺便说一句。因为(OR)是问题中给出的更简单的解决方案。
–greenoldman
18年8月14日在22:18
@greenoldman逻辑很简单:for将在列表中的所有单词/模式上循环,如果在文件中找到它,则将其打印出来。因此,如果您不需要采取措施以防找不到单词,只需删除else即可。
– Noam Manos
18年8月16日在15:07
我理解您的逻辑以及我的问题-我在问AND运算符,这意味着如果文件与模式A和模式B以及模式C和...匹配,则文件仅是肯定命中,并且...它匹配模式A或模式B或...您现在看到区别了吗?
–greenoldman
18年8月17日在6:19
@greenoldman不确定为什么您认为此循环不检查所有模式的AND条件?因此,我用一个真实的示例编辑了我的答案:它将在文件中搜索列表的所有正则表达式,并且在第一个缺失的正则表达式中-会错误退出。
– Noam Manos
18年8月19日在15:04
您将它放在眼前,在执行第一个比赛之后就拥有正面比赛。您应该“收集”所有结果并对其进行计算和。然后,您应该重写脚本以在多个文件上运行-然后,也许您意识到问题已经得到回答,并且您的尝试没有带来任何好处,对不起。
–greenoldman
18年8月20日在5:56
评论
相似:一次匹配文件中的所有模式关于SO的类似问题:检查文件中是否存在多个字符串或正则表达式
如果要查找“包含foo的行和包含bar的行”的grep语法,请参阅对多个搜索模式使用grep