regex - 将 GNU sed 命令移植到 BSD sed

标签 regex linux bash sed freebsd

我正在将一个为 Linux 编写的 shell 脚本移植到 FreeBSD,并且遇到了这一行:

local from_conf="$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)"

它用作从配置文件($CONF)中获取属性的函数的一部分,因此添加实际变量值可能类似于:

local from_conf="$(sed -rn "s/^USERNAME=('|\"|)(.*)\1/\2/ip" "/etc/msm.conf" | tail -n 1)"

在 GNU sed(Ubuntu 中的 v4.2.2)下,这按要求工作,但是在 BSD sed(在 FreeBSD 10.1 中提供)下,它提示:

sed: 1: "s/^USERNAME=('|"|)(.*)\ ...": RE error: empty (sub)expression

它似乎是模式的 ('|"|) 部分中的第二个管道,删除它( ('|") )清除错误,并且我在 FreeBSD 上得到了想要的结果。它还似乎在 Ubuntu 下给出了正确的结果,但由于我正在尝试编写可在两个系统之间移植的代码,我想更好地理解表达式的这一部分以及为什么它不不能在 BSD sed 下工作。


我对原始模式 ( ('|"|) ) 的理解是:

匹配:

  • 单引号 (') — 例如用户名='foo'
  • 双引号 (") — 例如 LOCALE="bar"
  • nothing () — 例如延迟=10

如何在不破坏 GNU sed 的情况下将此模式移植到 BSD?


还有一个元素不起作用:

sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF"

\1 是模式的一部分,在 GNU 下 sed 将插入 ('|\"|) 的任何结果。这是行不通的在 BSD sed 下,是否有不同的、可移植的符号?或者我是否必须逐字重复第一个模式?


编辑: /etc/msm.conf 的内容可能如下所示:

USERNAME='foo'
LOCALE="bar"
DELAY=10
SERVER_NAME="Ben's Server"

sed -rn "s/^USERNAME=('|\"|)(.*)\1/\2/ip""/etc/msm.conf" 的预期输出应该是“foo”。

最佳答案

这应该与删除的第一个捕获组一起使用

sed "s/^USERNAME=\(['\"]\)\{0,1\}\([^'\"]*\)['\"]\{0,1\}/\2/p;d" "/etc/msm.conf"

关于regex - 将 GNU sed 命令移植到 BSD sed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31003678/

相关文章:

c++ - 语法错误 : "(" unexpected

mysql - 将句点保存在首字母缩略词中还是不保存在数据库中?

regex - 使用正则表达式将 Excel 公式转换为 Wolfram Mathematica

javascript - 非法第一个字符的正则表达式

php - 更好的 strip 化方法 php 正则表达式

linux - bash - 用引号将所有数组元素或参数括起来

java - 支持使用 FUSE-J 在 FUSE 文件系统中进行写操作

linux - 无法反汇编我的应用程序——未找到调试信息

linux - 将 .txt 中的 html 结构转换为 .html 文件的 <body>

bash - 将项目目录设置为Dockerfile中Entrypoint的Workdir