我想在 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
是我的正则表达式。
我错过了什么?
最佳答案
\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:]])
请注意,我去掉了开头的 ^.*
和结尾的 .*$
,因为这些结构在进行非锚定匹配时会 self 否定; .*
使紧接在它前面的 ^
变得毫无意义,同样地 .*
就在最后的 $
之前.
现在,如果你想要一个 exact 等同于 \b
紧接在序列开头的单词字符之前,那么我们会得到更像的东西:
(^|[^a-zA-Z0-9_])
...同样,当紧跟在序列末尾的单词字符之后时:
($|[^a-zA-Z0-9_])
这两种情况都有些退化——在其他情况下,在 ERE 中模拟 \b
的行为可能会更复杂——但它们是你的问题出现的唯一情况.
请注意,\b
的某些实现会更好地支持非 ASCII 字符集,因此可以用 [^[:alnum:]_] 更好地描述
而不是 [^a-zA-Z0-9_]
,但这里没有明确定义您来自哪个实现或与之比较。
关于regex - 使用 Bash 正则表达式匹配单词边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27476347/