我想在bash中匹配以下表达式:
^.*(\b((720p)|(1080p)|(((br)|(hd)|(bd)|(web)|(dvd))rip)|((x|h)264)|(DVDscr)|(xvid)|(hdtv)|(ac3)|(s[0-9]{2}e[0-9]{2})|(avi)|(mp4)|(mkv)|(eztv)|(YIFY))\b).*$
我真想知道的是,测试字符串中的一个单词是否是此正则表达式中描述的单词之一(720p
,1080p
,brrip
,... )。而边界这个词似乎存在问题。
我使用的测试是[[ $name =~ $re ]] && echo "yes"
,其中$name
是任意字符串,$re
是我的正则表达式。
我错过了什么?
答案 0 :(得分:4)
\b
是PCRE扩展名;它在POSIX ERE(扩展正则表达式)中不可用,这是bash =~
中的[[ ]]
运算符将遵循的最小可能语法集。 (单个操作系统可能具有扩展此语法的libc;在这种情况下,这些扩展将在此类操作系统上可用,但在支持bash的所有平台上不。)
作为基线,\b
扩展实际上并没有非常强大的表达力 - 您可以编写任何使用它作为等效ERE的PCRE。但更好的是退后一步并质疑潜在的假设:当你说"字边界"时,你的意思是什么?如果您关心的是,如果以空格或字符串的开头或结尾开始和结束,那么您根本不需要\b
运算符:
(^|[[:space:]])((720p)|(1080p)|(((br)|(hd)|(bd)|(web)|(dvd))rip)|((x|h)264)|(DVDscr)|(xvid)|(hdtv)|(ac3)|(s[0-9]{2}e[0-9]{2})|(avi)|(mp4)|(mkv)|(eztv)|(YIFY))($|[[:space:]])
请注意,我取出了最初的^.*
并结束了.*$
,因为这些结构在进行其他非锚定匹配时会自我否定; .*
会使紧接其前面的^
变得毫无意义,而.*
恰好位于最后$
之前。
现在,如果你想要一个完全等同于\b
,当它紧接在一个序列开头的单词字符之前,那么我们会得到更像:
(^|[^a-zA-Z0-9_])
......同样,紧接在序列末尾的单词字符之后:
($|[^a-zA-Z0-9_])
这些都是有些堕落的情况 - 在其他情况下,模仿ERE中\b
的行为可能会更复杂 - 但它们是您的问题似乎呈现的唯一情况。< / p>
请注意,\b
的某些实现可以更好地支持非ASCII字符集,因此可以使用[^[:alnum:]_]
而不是[^a-zA-Z0-9_]
更好地进行描述,但它不是在这里明确定义了您来自或比较的实施。
答案 1 :(得分:1)
接受的答案错误可能在两个小问题上有误:
\b
和&#39; \&lt; |&gt;&#39; (字边界匹配)不是PCRE的创新。再说一次,我无法在RE引擎中跟踪字边界匹配的介绍,所以它也可能是Perl。也就是说,这个答案是非常具体到Linux
的{{1}}版本(最终Bash
特定部分,其中可以也适用于所有BSD衍生物)。
根据定义,GNU MacOSX
(Regular Expressions
)支持RE
和\b
作为字边界(\<|\>
语法)。 它不是 Perl兼容的正则表达式扩展,AFAIK。 [1]
grep
支持自Bash
以来的GNU扩展RE
(grep -E
语法)。 [2]
因此,对于3.0
的所有版本,Bash >= 3.0
应该给我[[ " h " =~ '\bh\b' ]] && echo yes || echo no
。它没有(见下一点)。
在yes
个版本Bash
到3.0
,3.1
会给我[[ " h " =~ '\bh\b' ]] && echo yes || echo no
。请注意,模式本身是yes
运算符的right hand side
(RHS
)参数。 [2]
=~
更改了匹配运算符Bash-3.2
的引用规则。 [2]
从=~
开始,理想情况下应将模式存储在变量中,并将变量作为Bash-3.2
运算符提供给RHS
运算符:=~
。原因是引用规则发生了变化,因此如果模式在引号(pat='\bh\b' ; [[ " h " =~ $pat ]] && echo yes || echo no
或''
)内提供,则模式将被解释为字符串而不是正则表达式。 [2]
最后,您的模式是正确的,它只是一个奇怪的引用问题:
""
此外,对于[samveen@ankhmorpork ~]# echo $BASH_VERSION
4.2.46(1)-release
[samveen@ankhmorpork ~]# re='^.*(\b((720p)|(1080p)|(((br)|(hd)|(bd)|(web)|(dvd))rip)|((x|h)264)|(DVDscr)|(xvid)|(hdtv)|(ac3)|(s[0-9]{2}e[0-9]{2})|(avi)|(mp4)|(mkv)|(eztv)|(YIFY))\b).*$'
[samveen@ankhmorpork ~]# for i in 720p 1080p brrip; do
> [[ $i =~ $re ]] && echo yes for $i || echo no for $i
> done
yes for 720p
yes for 1080p
yes for brrip
上的Bash
,边界匹配从MacOSX
更改为\b
(单词的开头)和'[[:<:]]
(单词结尾) [3]:
[[:>:]]
参考文献:
[1] GNU grep Manual: Regex section