【问题标题】:Bash script to replace or append用于替换或附加的 Bash 脚本
【发布时间】:2015-05-17 14:51:34
【问题描述】:

我是 Bash 脚本的新手,我遇到了一些困难。我正在尝试更改配置文件的配置值。如果它找到一个现有值,我希望它更新它,但如果它不存在,我希望它附加它。这是我从各种教程和在线 sn-ps 中得到的:

# FUNCTION TO MODIFY CONFIG BY APPEND OR REPLACE
# $1 File
# $2 Find
# $3 Replace / Append
function replaceappend() {
    grep -q '^$2' $1
    sed -i 's/^$2.*/$3/' $1
    echo '$3' >> $1
}

replaceappend "/etc/test.conf" "Port 20" "Port 10"

但是,正如您想象的那样,这行不通。似乎与它背后的逻辑有关,我不确定如何捕获 grep 的结果以便选择 sed 或 echo。

【问题讨论】:

  • 变量不会在单引号字符串中展开。
  • 获取grep命令的退出码。
  • @Gumbo 我应该将它们更改为双引号字符串吗?
  • 类似但不密切相关的关于处理配置文件的帖子,请看这篇帖子:stackoverflow.com/a/20268787/234110

标签: bash shell security sed grep


【解决方案1】:

只用命令的返回值,用双引号代替单引号:

if ! sed -i "/$2/{s//$3/;h};"'${x;/./{x;q0};x;q1}' $1
then
    echo "$3" >> $1
fi

来源:Return code of sed for no match 用于 q 命令

这超出了我对 sed 的正常使用范围,所以让我解释一下它是如何工作的,据我所知:

sed "/$2/{s//$3/;h};"'${x;/./{x;q0};x;q1}' $1

第一个/$2/ 是一个地址——我们将在{...} 中对任何与此匹配的行执行命令。作为副产品,它还将模式空间设置为$2

命令{s//$3/;h} 表示用$3 替换模式空间中的任何内容,然后将模式空间保存在“保持空间”中,这是 sed 中的一种缓冲区。

单引号后的$ 是另一个地址 - 它表示在最后一行执行下一条命令。

命令{x;/./{x;q0};x;q1} 说:

  • x = 交换保持空间和模式空间
  • /./ = 匹配任何内容的地址
  • {x;q0} = 交换保持空间和模式空间 - 如果成功(保持空间中有东西)然后 q0=exit with 0 status(成功)
  • x;q1 = 交换保持空间和模式空间 - 因为现在这是成功的(由于之前的 x)然后 q1=exit with 1 status (fail)

第一部分的双引号允许替换$2$3。后半部分的单引号可防止错误替换 $

有点复杂,但只要文件中有内容,它似乎就可以工作。空文件仍然会成功,因为您在最后一行没有得到任何匹配项。

说实话,在所有这些复杂性之后......除非您正在使用的文件真的很长,以至于双通道真的很糟糕,否则我可能会像这样回到grep 解决方案:

if grep -q "^$2" $1
then
    sed -i "s/^$2.*$/$3/" $1
else
    echo "$3" >>$1
fi

这在以后更容易理解和维护......

【讨论】:

  • 如果你愿意,你可以弄乱grep,然后在其他地方做sed,但是直接使用sed的返回值更容易/更快。
  • 虽然我同意将其保存在 sed 中,但无论您是否找到该值,sed 都会返回相同的结果我认为。为此,我认为您需要使用 q 标志,但我不明白如何使用它
  • 感谢您非常全面的回答
猜你喜欢
  • 2014-02-16
  • 2011-02-17
  • 1970-01-01
  • 2018-07-02
  • 2021-03-01
  • 1970-01-01
  • 2022-07-21
  • 2017-03-10
  • 2010-11-29
相关资源
最近更新 更多