sed:如果找到变量行则如何替换,如果未找到则如何附加到文件末尾?

sed:如果找到变量行则如何替换,如果未找到则如何附加到文件末尾?

所以我的问题很大程度上是基于相关问题,但有一个关键的区别。

在给出的答案中:

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile

我做了一个变体,用于创建FOOBAR变量(例如,程序的名称,然后将其放入 for 循环中以生成程序及其安装状态的列表)。这是针对我正在开展的一个相当复杂的项目,目的是使为 Raspberry Pi 安装 Drawile 并启用一些新功能,但这是另外一个棘手的问题,我不想深入探讨。

sed -i '/^'"$FOOBAR"'=/{h;s/=.*/=newvalue/};${x;/^$/{s//'"FOOBAR"'=newvalue/;H};x}' infile

我希望newvalue成为$variable可以在脚本中更改的。我只是不知道如何让它工作,简单地使用'"做不到。我花了几个小时浏览和尝试阅读教程,但我理解得不够,并且已经深入研究了 sed 的内部工作原理。大多数情况下,这个变量会很简单,例如:yesnoerror。但是,我可能还会用它来表示文件夹和文件路径……所以我也担心/这里的替换。即使这不是一个完整的答案,只要我能找到更好地理解这一点所需的方向,我也很乐意自己弄清楚。


编辑:由于我确定我遗漏了一些基本知识,所以没有太多内容可以发布,我只是尝试了将 newvalue 括起来的各种方法。例如:

sed -i '/^FOOBAR=/{h;s/=.*/=$newvalue/};${x;/^$/{s//FOOBAR=$newvalue/;H};x}' infile

输出:FOOBAR = $newvalue
这是不正确的。应该输出存储的值newvalue

sed -i '/^FOOBAR=/{h;s/=.*/="$newvalue"/};${x;/^$/{s//FOOBAR="$newvalue"/;H};x}' infile

输出:FOOBAR = "$newvalue"
这是不正确的。应该输出存储的值newvalue

sed -i '/^FOOBAR=/{h;s/=.*/='"$newvalue"'/};${x;/^$/{s//FOOBAR='"$newvalue"'/;H};x}' infile

输出:sed: -e expression #1, char 30: unknown option to `s'

如果newvalue等于Yes,那么我希望输出是FOOBAR = Yes或可能是文件夹路径。

答案1

我们来看一下 的基本形式sed

用法:sed [OPTION]... {script-only-if-no-other-script} [input-file]...

这就是我得出的答案。

sed -i '\!^'"$FOOBAR"'=!{h;s!=.*!='"$newvalue"'!};${x;\!^$!{s!!'"$FOOBAR"'='"$newvalue"'!;H};x}' /home/pi/Public/test.txt

从左到右的解释:

  • -i用于就地编辑文件,即无需备份即可编辑原始文件。
  • '用于启动我们将用来实现目标的表达式脚本。
  • !必须用来代替典型的/分隔符,因为我们期望输入可能/在文件夹或文件路径中使用。第一个感叹号被转义以确保它被正确解释
  • 第一部分寻找现存的复制任何内容$FOOBAR,例如apache2程序安装状态。以下要点特定于我们的 sed 查询的这一部分。
    • ^是一个正则表达式,表示它将匹配行的起始位置。这意味着它将匹配$FOOBAR行的开头,而不是以下任何内容:$FOOBARTHIS IS $FOOBAR等。
    • '""'包围$FOOBAR,因为它是确保脚本正确解释变量所必需的。如果没有它,它最终会打印$FOOBAR到文档中,而不是变量包含的值$FOOBAR。后面的等号只是我们正在寻找的预期文本部分的一部分。
    • 用于{对命令进行分组。
    • h命令将模式缓冲区复制到保留缓冲区中以供稍后使用。这是一个单行缓冲区,因此它一次不能容纳多行。
    • ;命令用于将多个 sed 命令合并到一行中。不幸的是,它的文档似乎相当少。您可以在此处阅读更多信息http://www.grymoire.com/Unix/Sed.html#uh-61
    • 表示s将使用新模式的一部分来替代。
    • .*是一个正则表达式,在本例中,表示在新行开始之前查找等号后跟任意数量的字符。它将用等号后跟 替换它$newvalue,例如= yes= no。变量$newvalue被 包围'",并且"'出于同样的原因$FOOBAR包含它们。然后我们输入最后一个分隔符并关闭分组命令。
  • 这是 sed 命令的第二部分。以下要点特定于 sed 查询的这一部分。重复的部分将被跳过。
    • 查找$文件最后一行的结尾。然后我们开始新的分组命令系列。
    • x模式空间与保持缓冲区进行交换。这是我自己有点糊涂的部分,但在我看来,此时 sed 正在修改整个文件,如此处所述。我试图在最后一点中对此进行更多解释。在此处阅读更多内容 -http://www.grymoire.com/Unix/Sed.html#uh-53
    • ^$意味着我们正在寻找一个段落返回,它既是行的开始也是行的结束,并且这一行上没有任何类型的字符。
    • 然后我们继续用双定界符感叹号替换该无字符行,并用变量$FOOBAR和替换该值$newvalue
    • H小写字母相同,h它是一个保留缓冲区,但用于多行。我们关闭该分组并再次用 替换它x。这基本上是首先在文档顶部插入我们想要的行。Sed 逐行浏览文档,取出其下方的行并将其移动到我们插入的行上方。由于 sed 的工作方式类似于“管道”,是一个流编辑器,它会一直这样做,直到到达文档末尾并停止处理更改。
  • 最后是需要修改的文件:/home/pi/Public/test.txt

我想我已经解释清楚了一切,欢迎反馈。

相关内容