Regex 将GNU sed命令移植到BSD sed
我正在将一个为Linux编写的shell脚本移植到FreeBSD,遇到了以下问题:Regex 将GNU sed命令移植到BSD sed,regex,linux,bash,sed,freebsd,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 -
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下不起作用
我对原始模式(
('|“|”)
)的理解是:
匹配:
- 单引号(')-例如USERNAME='foo'
- 双引号(“)-例如LOCALE=“bar”
- 无()-例如延迟=10
还有一个元素不起作用:
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"
local from_conf=$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)
sed-rn“s/^USERNAME=('| \“|”)(.*)\1/\2/ip”“/etc/msm.conf”
的预期输出应该是“foo
”这应该适用于删除的第一个捕获组
sed "s/^USERNAME=\(['\"]\)\{0,1\}\([^'\"]*\)['\"]\{0,1\}/\2/p;d" "/etc/msm.conf"
这应该适用于删除的第一个捕获组
sed "s/^USERNAME=\(['\"]\)\{0,1\}\([^'\"]*\)['\"]\{0,1\}/\2/p;d" "/etc/msm.conf"
封闭脚本的引号错误。请删除外部双引号,如下所示:
USERNAME='foo'
LOCALE="bar"
DELAY=10
SERVER_NAME="Ben's Server"
local from_conf=$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)
你应该可以走了
至于(…)问题,请使用
\(
和\)
。这是可移植的表示法。您的封闭脚本有错误的引号。请消除外部双引号,如下所示:
USERNAME='foo'
LOCALE="bar"
DELAY=10
SERVER_NAME="Ben's Server"
local from_conf=$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)
你应该可以走了
至于(…)问题,使用
\(
和\)
。这是可移植的表示法。你能提供一个它匹配的示例字符串和匹配时的输出吗?我想用(['''''''')?)替换('\')
)
但是BSDsed
的结果似乎是空的,所以这不太可能有帮助。我正要提出同样的建议。可能是BSD sed抱怨中有一个空的子表达式(foo | bar |)
并不是说\1
是空的。无论如何,值得一试。我做了一点挖掘:foo
实际上在POSIX扩展正则表达式中无效,但GNU的实现支持它。这让我相信
表达式中的空子表达式是这里的问题,用['\]替换它?
(\“
仅因为它位于双引号外壳字符串中)应该可以解决此问题。@Wintermute?
在POSIX中无效,是吗?能否提供一个它匹配的示例字符串及其匹配时的输出?我想用('.\\“|”)
替换为([''“?)
但是BSDsed
的结果似乎是空的,所以这不太可能有帮助。我正要提出同样的建议。可能是BSD sed抱怨中有一个空的子表达式(foo | bar |)
并不是说\1
是空的。无论如何,值得一试。我做了一点挖掘:foo
实际上在POSIX扩展正则表达式中无效,但GNU的实现支持它。这让我相信
表达式中的空子表达式是这里的问题,用['\]替换它?
(\“
仅因为它位于双引号外壳字符串中)应该可以解决问题。@Wintermute?
在POSIX中无效,是吗?如果不需要,则$()
之外的引号可以。\(
和\)
不是可移植的符号,而是基本的正则表达式语法。OP使用扩展的正则表达式语法(请参阅-r
开关),其中\(
表示文字(
),与捕获组相对。在$()必须删除。这是导致他重新出错的原因,因为第一个引号与表达式中的一个未替换引号匹配。@子shell外部的DannyDaglas引号在其中看不到。引号没有问题。@DannyDaglas Shell支持$()
了解该上下文内的引号与该上下文外的引号不匹配。这没有问题。(如果您有一个shell不理解您的shell有问题。)请自己尝试并查看:v=“$(echo bar“foo”baz)”;echo“$v”
啊,是这样。Thx.$外的引号()(和)
不是可移植的符号,而是基本的正则表达式语法。OP使用扩展正则表达式语法(请参阅-r
开关),其中\(
表示文本(
与捕获组相对。$()必须删除。这是导致他重新出错的原因,因为第一个引号与表达式中的一个未替换引号匹配。@子shell外部的DannyDaglas引号在其中看不到。引号没有问题。@DannyDaglas Shell支持$()
了解该上下文内的引号与该上下文外的引号不匹配。这没有问题。(如果您有一个shell不了解您的shell有问题。)请自己尝试并查看:v=“$(echo bar“foo”baz)”;echo“$v”
啊,确实如此。Thx。这几乎可以工作,