sed:如果找到,如何替换行或如果未找到则追加到文件末尾?

Bla*_*Bat 43 linux awk sed command-line

使用仅包含注释(以 # 开头)和 VARIABLE=value 行的单个输入文件,是否可以在找到时替换单个变量的值,否则,如果未找到,则将该对附加到文件末尾?

我当前的方法是在第一遍中删除它,然后在第二遍中将其附加到文件的末尾,但这种方法会弄乱行顺序(也是两个不同的命令):

sed -r "/^FOOBAR=.*$/d"      -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点,即。在单个 sed 行中保持行序?如果其他一些实用程序(awk,...)这样做,我会把它接管 sed。

don*_*sti 42

它实际上非常简单sed:如果一行匹配,只需将其复制到h旧空间然后s替换该值。
在最后$一行 ex更改保留空间和模式空间,然后检查后者是否为空。如果它不为空,则表示已经进行了替换,因此无需执行任何操作。如果它为空,则意味着未找到匹配项,因此将模式空间替换为所需的变量=值,然后附加到保持缓冲区中的当前行。最后,ex再次改变:

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile
Run Code Online (Sandbox Code Playgroud)

以上是gnu sed语法。便携的:

sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案不是“简单”的,哈哈。但它有效。sed 手册页不是最容易筛选的内容,如果您能详细说明表达式每个部分的效果,那将非常有帮助:) (4认同)

har*_*dsv 24

这是一种更简单的sed方法,因为我觉得sed hold space使用起来并不容易。如果您对 感到满意hold space,则使用 don_crissti 方法可以提供额外的机会来保留现有行中的任何内容,但这通常非常罕见。

在这种方法中,您只需打印除要删除的行之外的所有内容,然后在最后添加替换内容。

sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!如果您不介意将现有行移到最后。谢谢!我更喜欢把它放在一个参数中:`sed -nr '/^FOOBAR=/!p;$aFOOBAR=newvalue' infile` (3认同)
  • 如果您计划更新可能具有现有但过时值的文件,则此版本非常好。 (2认同)

sna*_*hoe 19

这可能可以缩短。它不是一个单一的 sed 命令,它也使用 grep,但这似乎基本上是你想要的。这是一行,它就地编辑文件(没有临时文件)。

grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file || 
    sed "$ a\FOOBAR=newvalue" -i file
Run Code Online (Sandbox Code Playgroud)