这个regex表达式在sed(撇号括号)中没有关闭吗?

时间:2019-05-04 17:54:59

标签: regex sed

我正在尝试为wordpress更新一些设置,我需要使用sed。当我运行以下命令时,似乎认为该行未完成。我在做什么错了?

$ sed -i 's/define\( \'DB_NAME\', \'database_name_here\' \);/define\( \'DB_NAME\', \'wordpress\' \);/g' /usr/share/nginx/wordpress/wp-settings.php
> ^C

谢谢。

2 个答案:

答案 0 :(得分:4)

大多数shell中的单引号不支持任何转义。如果要包含单引号,则需要关闭单引号并添加单引号-可以使用双引号或反斜杠:

 sed 's/define\( '\''DB_NAME'\'', '\''database_name_here'\'' \);/define\( '\''DB_NAME'\'', '\''wordpress'\'' \);/g'

我担心它仍然对您不起作用,因为\(在sed中是特殊的。您可能只需要一个简单的(

sed 's/define( '\''DB_NAME'\'', '\''database_name_here'\'' );/define( '\''DB_NAME'\'', '\''wordpress'\'' );/g'

sed 's/define( '"'"'DB_NAME'"'"', '"'"'database_name_here'"'"' );/define( '"'"'DB_NAME'"'"', '"'"'wordpress'"'"' );/g'

答案 1 :(得分:1)

通常,在sed脚本的脚本周围使用单引号是明智的。在这种情况下,双引号会是一个更好的选择-sed脚本中除了单引号外没有shell元字符:

sed -e "s/define( 'DB_NAME', 'database_name_here' );/define( 'DB_NAME', 'wordpress' );/g" /usr/share/nginx/wordpress/wp-settings.php

或:

sed -e "s/\(define( 'DB_NAME', '\)database_name_here' );/\1wordpress' );/g" /usr/share/nginx/wordpress/wp-settings.php

甚至:

sed -e "/define( 'DB_NAME', 'database_name_here' );/s/database_name_here/wordpress/g" /usr/share/nginx/wordpress/wp-settings.php

要考虑的另一种方法是使用sed的{​​{1}}选项将脚本作为文件提供。这使您不必从外壳中转出脚本内容。缺点是您必须创建文件,使用它运行-f,然后删除该文件。对于当前任务来说,这可能太痛苦了,但它可能是明智的–当您不必担心脱壳时,它无疑可以使生活变得更轻松。

我不认为sed(全局替换)选项是否适用;您将在包含两个具有默认值的独立g操作的设置文件中找到几行?

基本代码正常工作后,您可以添加define DB_NAME选项。请注意,如果您曾经在macOS或基于BSD的系统上工作过,则需要提供后缀作为-i选项的额外参数(例如,-i为空后缀或否)备份;或-i '',以便能够在Linux(或更准确地说,与GNU -i.bak)以及macOS和BSD(或更确切地说,与BSD sed)上都能可靠地工作。吸引POSIX没有帮助;它不支持覆盖选项。

测试用例(第一个示例):

sed

如果$ echo "define( 'DB_NAME', 'database_name_here' );" | > sed -e "s/\(define( 'DB_NAME', '\)database_name_here' );/\1wordpress' );/g" define( 'DB_NAME', 'wordpress' ); $ 周围的间距不一致,那么您将得到更冗长的正则表达式,使用'DB_NAME'来代替空格,并且您会发现第三个替代方案比其他,但是第二个可以捕获前导和尾随上下文,并在替换中使用这两个捕获。

分词:这项技术这次有效,因为模式不涉及[[:space:]]*$之类的外壳元字符。通常,脚本确实需要匹配它们,然后在script参数周围使用主要的单引号是明智的。解决另一个任务—用外壳变量 ` 的值替换输入中的$DB_NAME(保持$DB_NAME不变):

$DB_NAMEORHOST

有三个单独的shell字符串,所有字符串都没有空格。第一个是单引号,包含sed -e 's/$DB_NAME\([^[:alnum:]]\)/'"$DB_NAME"'\1/' 命令的s/…/部分;第二个是s/…/…/,shell变量的值用双引号引起来,因此,如果"$DB_NAME"的值是“自动车辆记录”,则$DB_NAME仍然有一个参数;第三部分是sed部分,它放回输入文本中'\1/'之后的任何字符(观察到,如果$DB_NAME可能出现在输入行的末尾,则不会匹配)。

大多数正则表达式进行模糊匹配;您必须考虑输入内容的变化,以确定正则表达式必须多努力才能准确地识别材料。