【问题标题】:sed: Replace part of a linesed:替换一行的一部分
【发布时间】:2010-11-07 15:35:03
【问题描述】:

如何用 sed 替换一行的一部分?

线

DBSERVERNAME     xxx

应该替换为:

DBSERVERNAME     yyy

值 xxx 可以变化,并且在 dbservername 和值之间有两个选项卡。此名称-值对是配置文件中的许多对之一。

我尝试了以下反向引用:

echo "DBSERVERNAME    xxx" | sed -rne 's/\(dbservername\)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'

这导致了一个错误:'s' 命令的 RHS 上的无效引用 \1。

表达式有什么问题?使用 GNU sed。

【问题讨论】:

    标签: sed


    【解决方案1】:

    这行得通:

    sed -rne 's/(dbservername)\s+\w+/\1 yyy/gip'
    

    (当您使用 -r 选项时,您不必转义括号。)

    一点解释:

    • -r 是扩展的正则表达式 - 改变了正则表达式的编写方式。
    • -n 除非指定,否则不会打印 - sed 否则默认打印,
    • -e 表示它后面是一个表达式。让我们分解表达式:
      • s/// 是搜索替换的命令,第一对是要匹配的正则表达式,第二对是替换,
      • gip,跟在搜索替换命令之后; g 表示全局,即每个匹配项而不是第一个匹配项将被替换为一行; i 不区分大小写; p 表示完成后打印(记住之前的 -n 标志!),
      • 括号表示匹配部分,稍后会出现。所以dbservername是第一个匹配部分,
      • \s 是空格,+ 表示出现一次或多次(相对于 *,零次或多次),
      • \w 是一个单词,即任何字母、数字或下划线,
      • \1 是 GNU sed 的一个特殊表达式,它打印伴随搜索中的第一个括号匹配。

    【讨论】:

    • 我知道你们在 shell 命令方面有很多经验...但是请尽可能多地关心有抱负的 linux 新手...'' 中的所有内容都需要解释...或者我必须经过整个doc
    • 请注意,在模式中使用sed -n/p,这只会打印更改的行(过滤掉文件的其余部分),我不确定这是提问者想要的。 (与 sed -rpe 's/.../.../gi 相比,它会打印每一行,只更改匹配项。)
    【解决方案2】:

    其他人已经提到了括号的转义,但是如果行的第一部分是常量,为什么还需要反向引用呢?

    你可以这样做

    sed -e 's/dbservername.*$/dbservername yyy/g'
    

    【讨论】:

    • 好点!我刚刚了解了使用 regexps + sed 并且在看到这个特定任务时才决定使用“regexp”,然后正如“jwz”所说“我有两个问题”(尽管不是直接由于 regexps):)
    • 这得到了我的投票,因为它是解决简单问题的最简单方法。使用反向引用可以避免错误输入dbservername 的两个副本。这里很明显,但是当我在 sed 中修改 postgresql.conf 时,我发现很难一眼看出我输入的是 listen_address 还是 listen_addresses (postgresql.conf)。两者看起来都有道理,但只有一个是正确的。
    【解决方案3】:

    你正在逃避你的 ( 和 )。我很确定你不需要这样做。试试:

    sed -rne 's/(dbservername)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'

    【讨论】:

      【解决方案4】:

      当你使用单引号时,你不应该转义。即。

      echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername[[:blank:]]+)([[:alpha:]]+)/\1 yyy/gip'
      

      【讨论】:

        【解决方案5】:

        你不应该逃避你的父母。试试:

        echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername)[[:blank:]]+([[:alpha:]]+)/\1 yyy/gip'
        

        【讨论】:

          【解决方案6】:

          这可能对你有用:

          echo "DBSERVERNAME     xxx" | sed 's/\S*$/yyy/'
          DBSERVERNAME     yyy
          

          【讨论】:

            【解决方案7】:

            试试这个

            sed -re 's/DBSERVERNAME[ \t]*([^\S]+)/\yyy/ig' temp.txt

            或者这个

            awk '{if($1=="DBSERVERNAME") $2 ="YYY"} {print $0;}' temp.txt

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-08-13
              • 2023-04-07
              • 1970-01-01
              • 2014-05-31
              • 2016-09-15
              • 2017-04-30
              • 1970-01-01
              • 2012-03-10
              相关资源
              最近更新 更多