【问题标题】:Sed replace with shell variables [duplicate]Sed用shell变量替换[重复]
【发布时间】:2014-01-09 14:29:43
【问题描述】:

我正在尝试用 shell 变量实现 sed 替换。到目前为止,我已经将 sed 替换为 '

sed -i -r 's#(export\ PATH=")(.*)#\1/home/USER/bin:~/.local/bin:\2#' ~/.zshrc

但不幸的是,' 并没有像这个答案 https://stackoverflow.com/a/5156322/675100 中所述那样扩展 shell 变量

在尝试使用" 时,我一直遇到括号等问题。我想让这个通用的总是使用whoami 而不是USER

第一次尝试是

sed -i -r "s#\(export\ PATH=\"\)(.*)#\1/home/`whoami`/bin:~/.local/bin:\2#" ~/.zshrc
sed: -e expression #1, char 60: invalid reference \2 on `s' command's RHS

编辑

我试过了

sed -i -r "s#\(export\ PATH=\"\)\(.*\)#\1/home/$(whoami)/bin:~/.local/bin:\2#" ~/.zshrc

逃避第二组,但我得到了类似的错误:

sed: -e expression #1, char 63: invalid reference \2 on `s' command's RHS

【问题讨论】:

  • 请注意,只有$ 和反引号会导致双引号内出现问题;括号仅在前面有 $ 时才相关,如 $(whoami) 等。
  • 您转义了第一对括号,但没有转义 (.*) 周围的第二对括号。这就是为什么没有第二组可以用\2 引用的原因。另外,-r 是干什么用的?我的sed 没有那个……
  • 你为什么专门用​​/home/USER/bin而不是~/bin
  • @glennjackman 我已经尝试过了,但 zsh 无法正确识别 - 我不知道为什么。

标签: regex bash shell sed


【解决方案1】:

你可以这样写:

sed -i 's#export PATH="#&/home/'$(whoami)'/bin:~/.local/bin:#' ~/.zshrc

或者正如@glennjackman 指出的那样:

sed -i 's#export PATH="#&~/bin:~/.local/bin:#' ~/.zshrc

注意:

  • 您可以仅匹配 (start),使用 & 将其替换为自身,然后插入您的“newstuff”,而不是匹配 (start)(end) 并在 (start)"newstuff"(end) 之间插入。李>
  • 为简化引用,您可以随时结束单引号部分,稍后再开始新的单引号部分,因为它们是等价的:

    echo 'hello there'
    echo 'hello'' there'
    

【讨论】:

    【解决方案2】:

    反斜杠转义是在双引号字符串中执行的,因此您必须转义所有反斜杠!

    sed -i -r "s#\\(export PATH=\"\\)\\(.*\\)#\\1/home/$(whoami)/bin:~/.local/bin:\\2#" ~/.zshrc
    

    我会使用以下方法之一来确定用户的主目录。

    sed -i -r "s#\\(export PATH=\"\\)\\(.*\\)#\1~/bin:~/.local/bin:\\2#" ~/.zshrc
    sed -i -r "s#\\(export PATH=\"\\)\\(.*\\)#\1$HOME/bin:~/.local/bin:\\2#" ~/.zshrc
    sed -i -r "s#\\(export PATH=\"\\)\\(.*\\)#\1$(getent passwd $LOGNAME | cut -d: -f6)/bin:~/.local/bin:\\2#" ~/.zshrc
    

    你的整个方法看起来很脆弱。

    • 如果 PATH 已经导出,我使用 PATH="..." 怎么办?
    • 如果我使用单引号会怎样?
    • 如果我使用不同的点文件怎么办?

    你为什么不直接使用

    PATH="~/bin:~/.local/bin:$PATH"
    

    ??

    【讨论】:

      【解决方案3】:

      好的,问题在于使用扩展正则表达式的-r 标志。

      最终的解决方案是使用:

      sed -i "s#\(export\ PATH=\"\)\(.*\)#\1/home/$(whoami)/bin:~/\.local/bin:\2#" ~/.zshrc 
      

      【讨论】:

        猜你喜欢
        • 2016-10-06
        • 2018-07-28
        • 2018-03-23
        • 2011-10-04
        • 2021-09-28
        • 2020-04-13
        • 1970-01-01
        • 2011-07-06
        • 2011-12-02
        相关资源
        最近更新 更多