Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 将GNU sed命令移植到BSD sed_Regex_Linux_Bash_Sed_Freebsd - Fatal编程技术网

Regex 将GNU sed命令移植到BSD sed

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 -

我正在将一个为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下不起作用


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

匹配:

  • 单引号(')-例如USERNAME='foo'
  • 双引号(“)-例如LOCALE=“bar”
  • 无()-例如延迟=10
如何将此模式移植到BSD而不中断GNU使用?


还有一个元素不起作用:

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)
你应该可以走了


至于(…)问题,使用
\(
\)
。这是可移植的表示法。

你能提供一个它匹配的示例字符串和匹配时的输出吗?我想用
(['''''''')?)替换
('\')
但是BSD
sed
的结果似乎是空的,所以这不太可能有帮助。我正要提出同样的建议。可能是BSD sed抱怨
中有一个空的子表达式(foo | bar |)
并不是说
\1
是空的。无论如何,值得一试。我做了一点挖掘:
foo
实际上在POSIX扩展正则表达式中无效,但GNU的实现支持它。这让我相信
表达式中的空子表达式是这里的问题,用
['\]替换它?
\“
仅因为它位于双引号外壳字符串中)应该可以解决此问题。@Wintermute
在POSIX中无效,是吗?能否提供一个它匹配的示例字符串及其匹配时的输出?我想用
('.\\“|”)
替换为
([''“?)
但是BSD
sed
的结果似乎是空的,所以这不太可能有帮助。我正要提出同样的建议。可能是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。这几乎可以工作,