正则表达式匹配与特定字符串耦合但不包含第三个字符串的任何字符串

时间:2018-07-11 09:02:12

标签: regex bash shell sed find

我想匹配包含列表中的单词的所有目录, AND 单词test,但不要单词DAT

EB80
TF90
UI11
POSPO02

因此,如果字符串中包含上述任何模式,并且字符串中也包含单词test,则该字符串为匹配项。但是字符串DAT绝不能在比赛中的任何地方。

我有此正则表达式,但似乎无法正常工作:

EB80 | TF90 | UI11 | POSPO02 [^DAT]test$

find . -regextype sed -regex "EB80 | TF90 | UI11 | POSPO02 [^DAT]test$"

3 个答案:

答案 0 :(得分:2)

不太优雅,但基本的find

$ ls
DATtestTF90 EB80test    POSPO02test UI11

$ find . -name "*DAT*" -prune -o -name "*test*" \( -name "*EB80*" -o -name "*TF90*" -o -name "*UI11*" -o -name "*POSPO02*" \) -print
./POSPO02test
./EB80test

要查找的参数可以理解为:

-如果名称匹配"*DAT*",请停止! (-prune),然后继续进行下去(另请参见:What does -prune option in find do?

-否则(-o),如果名称与"*test*"匹配并且名称包含任何给定的模式,则输出名称(-print

括号的作用与您在典型的编程语言中所期望的一样。默认情况下,任何两个谓词都具有AND关系,但是可以用-o覆盖以提供OR关系。用手册页的话说,括号是用来“强制优先”的,同样,我敢肯定,您习惯于其他语言。因此,您可以将查找内容的第二部分读为

name == "*test*" AND (name=="*EB80*" OR name=="*TF90*" OR name=="*UI11*" OR name=="*POSPO02*")

请注意,因为括号对外壳有意义,所以需要转义括号,以便find完整地接收它们。

答案 1 :(得分:1)

您不能在单个正则表达式(a or b) and c and !d中表达这些字符实际上是字符串。即使他们只是字符,试图在单个正则表达式中表达它,如果有可能的话,也将是一团糟。 [^DAT]的意思是not (D or A or T),顺带一句-[]是括号表达式,因此包含字符组,而不是字符串。

您应该考虑使用awk来匹配要对find输出进行后处理的条件。简直就是:

find . -type d -print |
awk '/EB80|TF90|UI11|POSPO02/ && /test/ && !/DAT/'

因为将需要的内容作为条件而不是单个正则表达式来编写是很简单的。如果您的文件名可以包含换行符,那么使用GNU find和GNU awk,只需将NUL用作文件名终止符即可,而不是换行符:

find . -type d -print0 |
awk -v RS='\0' '/EB80|TF90|UI11|POSPO02/ && /test/ && !/DAT/'

很显然,您可以将某些条件添加到查找中,如果您关心效率,可以将其从awk中删除,但是如果将整个条件放在上述一个位置,则可能会更容易维护。

答案 2 :(得分:0)

有些人会争辩说我产生了太多的proc,但是有时可读性也很重要,由于您没有明确说出一种或另一种方式,所以我将假定这些字符串的顺序无关紧要。怎么样-

find . -type d -name \*test\* | 
  grep -v DAT | egrep "EB80|TF90|UI11|POSPO02"

快速测试-

$: mkdir footestbar
$: mkdir footestbarDAT
$: mkdir footestbarDATEB80
$: mkdir footestbarEB80
$: find . -type d -name \*test\* |
>       grep -v DAT | egrep "EB80|TF90|UI11|POSPO02"
./footestbarEB80
相关问题