我正在将为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错误:空(子)表达式
它似乎是模式的('|"|)
部分中的第二个管道,删除它(('|")
)清除错误,我在FreeBSD上得到了所需的结果。它也出现以在Ubuntu下提供正确的结果,但由于我正在尝试在两个系统之间创建可移植的代码,我想更好地理解表达式的这一部分以及为什么它不能在BSD sed下工作。
我对原始模式(('|"|)
)的理解是:
匹配度:
如何在不破坏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
”。
答案 0 :(得分:1)
这应该适用于删除的第一个捕获组
sed "s/^USERNAME=\(['\"]\)\{0,1\}\([^'\"]*\)['\"]\{0,1\}/\2/p;d" "/etc/msm.conf"
答案 1 :(得分:-2)
你的封闭脚本引用不好。消除这样的外部双引号:
local from_conf=$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)
你应该好好去。
关于(...)问题,请使用\(
和\)
。这是便携式符号。