regex - 将 PCRE 模式转换为 POSIX

标签 regex sed

我有以下运行良好的 pcre:

/[c,f]=("(?:[a-z A-Z 0-9]|-|_|\/)+\.(?:js|html)")/g

它根据输入生成所需的输出“foo.js”和“bar.html”

<script src="foo.js"...
<link rel="import" href="bar.html"...

问题是,OS X 版本的 grep 似乎没有像 -o 这样的选项来只打印捕获的组(根据另一个 SO 问题,这显然适用于 linux)。由于这将是 makefile 的一部分,我需要一个可以在任何 *nix 平台上运行的版本。

我尝试了 sed 但以下内容

s/[c,f]=("(?:[[:alphanum:]]|-|_|\/)+\.(?:js|html)")/\1/pg

抛出错误:“重复运算符的操作数无效”。我试过将其删除,不包括文件路径分隔符,我似乎无法破解它。将我的 pcre 转换成我几乎可以保证在符合 POSIX 标准(即使是非官方的)平台上的东西有什么帮助吗?

附言我知道我编写的正则表达式中固有的潜在故障模式,它只会用于具有相当特定格式的非常特定的文件。

最佳答案

POSIX 定义了两种风格正则表达式:

  • BREs (Basic Regular Expressions) - 功能较少且需要 \ 的旧版本-转义某些元字符,特别是 \( , \)\{ , \} , 并且支持重复符号 \+ (用 \{1,\} 模拟)和 \? (用 \{0,1\} 模拟),支持 \| (交替;无法被模拟)。

  • EREs (Extended Regular Expressions) - 更现代的风格,但是缺少正则表达式内部的反向引用(这与捕获组相同); 支持词边界断言(例如\<),支持捕获组.

POSIX 还规定哪些实用程序支持哪种风格:哪些支持 BRE,哪些支持 ERE,哪些可选支持任一个,哪些 em>专门仅支持 BRE,或仅支持 ERE;特别是:

  • grep默认使用 BRE,但可以使用 -E 启用 ERE
  • sed ,遗憾的是,只有支持 BRE
    • GNU 和 BSD sed ,但是,- 作为一个非标准扩展 - 确实 支持带有 -E 的 ERE开关(GNU sed 的更广为人知的别名是 -r ,但也支持 -E)。
  • awk 支持ERE

此外,Linux 和 BSD/OSX 上的正则表达式库实现了对 POSIX ERE 语法的扩展 - 遗憾的是,这些扩展部分不兼容(例如单词边界断言的语法)。

至于您的特定正则表达式:

它使用捕获组的语法,(?:...) ;但是,捕获组在 grep 的上下文中毫无意义,因为 grep不提供替换功能。

如果我们删除这个方面,我们得到:

[c,f]=("([a-z A-Z 0-9]|-|_|\/)+\.(js|html)") 

现在这是一个有效的 POSIX ERE(可以简化 - 参见 Benjamin W's helpful answer)。
然而,由于它是一个扩展 RE,使用sed 不是一个选项,如果你想保持严格的 POSIX 兼容。

因为 GNU 和 BSD/OSX sed恰好实现-E为了支持 ERE,您可以逃脱 sed ,如果这些平台是您唯一需要支持的平台 - 请参阅 anubhava's answer .

同样,GNU 和 BSD/OSX grep碰巧实现了非标准 -o选项(与您在问题中陈述的不同),因此,如果这些平台是您唯一需要支持的平台,您可以使用:

$ grep -Eo '[c,f]=("([a-z A-Z 0-9]|-|_|\/)+\.(js|html)")' file | cut -c 3-
c="foo.js"
f="bar.html"

(请注意,只有 GNU grep 支持 -P 以启用 PCRE,这只是解决方案(请注意 \K,它会丢弃目前匹配的所有内容):

$ grep -Po '[c,f]=\K("([a-z A-Z 0-9]|-|_|\/)+\.(js|html)")' file

)

如果您真的想要严格符合 POSIX 标准的解决方案,您可以使用awk :

$ awk -F\" '/[c,f]=("([a-z A-Z 0-9]|-|_|\/)+\.(js|html)")/ { print "\"" $2 "\"" }' file

关于regex - 将 PCRE 模式转换为 POSIX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35686860/

相关文章:

java - IP 和字符串的正则表达式

java - 以 "?"作为 clown 的字符串搜索?

bash - 如何使用 sed 替换文件中第三次出现的同一正则表达式?

linux - 解析和替换两个文件中的一些字符串

java - [^\d].* 和 ^[^\d].* 在 java 正则表达式中的区别

python - 匹配以逗号分隔的精确长度的所有单词

Python 匹配路径中的字符串并替换为先前的路径项

regex - {$TENANTCODE$} 的 sed 转义规则

linux - sed 代码以匹配 http ://www. domain.com/并在目录中的所有文件中仅替换为 a/

bash - 在 bash/awk 中检测一系列数字是否连续