Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.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
要替换或追加的Bash脚本_Bash_Shell_Security_Sed_Grep - Fatal编程技术网

要替换或追加的Bash脚本

要替换或追加的Bash脚本,bash,shell,security,sed,grep,Bash,Shell,Security,Sed,Grep,我不熟悉Bash脚本,现在有点困难。我正在尝试更改配置文件的配置值。如果它找到一个现有值,我希望它更新它,但如果它不存在,我希望它附加它。这是我从各种在线教程和片段中得到的: # 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/

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

# 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。

只需使用命令的返回值,并使用双引号而不是单引号:

if ! sed -i "/$2/{s//$3/;h};"'${x;/./{x;q0};x;q1}' $1
then
    echo "$3" >> $1
fi
来源:对于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=以0状态退出(成功)
  • x;q1
    =交换保持空间和图案空间-由于现在成功(由于上一个x),因此q1=退出,状态为1(失败)
第一部分周围的双引号允许替换
$2
$3
。后面部分的单引号可防止错误地替换
$

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

老实说,经历了这么多复杂的事情。。。除非您正在处理的文件非常长,以至于双过程非常糟糕,否则我可能会回到
grep
解决方案,如下所示:

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

这一点以后更容易理解和维护…

变量不会在单引号字符串中展开。获取grep命令的退出代码。@Gumbo我应该将其更改为双引号字符串吗?类似,但不是关于处理配置文件的密切相关帖子,看看这篇文章:如果你愿意,你可以搞乱
grep
,然后在else中执行
sed
,但是直接使用
sed
的返回值更容易/更快。虽然我同意将其保留在sed中,但不管你是否找到值,sed都会返回相同的值。为此,我认为你需要使用
q
标志,但我不知道如何使用它谢谢你非常全面的回答