【问题标题】:Linux Replace With Variable Containing Double QuotesLinux 替换为包含双引号的变量
【发布时间】:2018-03-24 21:44:46
【问题描述】:

我已阅读以下内容:

我了解到我可以使用sed "s/STRING/$var1/g" 将字符串替换为变量的内容。但是,我很难找出如何用包含双引号、方括号和感叹号的变量替换。

然后,为了避免引号,我尝试通过sed 's/\"/\\\"/g' 传递我的结果,这给了我另一个错误sed: -e expression #1, char 7: unknown command: E'。我希望避开有问题的字符,然后进行变量替换:sed "s/STRING/$var1/g"。但我也没能走到那一步。

我想你们可能知道用包含引号的变量替换字符串的更好方法。

文件1.txt:

Example test here
<tag>"Hello! [world]" This line sucks!</tag>
End example file

变量:

var1=$(cat file1.txt)

例子:

echo "STRING" | sed "s/STRING/$var1/g"

期望的输出:

Example test here
<tag>"Hello! [world]" This line sucks!</tag>
End example file

【问题讨论】:

  • sed 不是这种替换的正确工具。
  • @anubhava 我明白了。感谢阿努巴瓦的建议。我对任何可行的事情都持开放态度。也会尝试做更多的研究。编辑问题以反映这一点。
  • @batMan 是的,就是这样。保持变量中的数据相同。我想用$var1 的内容替换STRING。这就是我卡住的地方。这只是一个极简主义的例子。

标签: regex linux bash awk sed


【解决方案1】:

使用 awk

$ echo "STRING" | awk -v var="$var1" '{ gsub(/STRING/,var,$0); print $0}'
Example test here
<tag>"Hello! [world]" This line sucks!</tag>
End example file

-v var="$var1":在 awk 中使用 shell 变量
gsub(/STRING/,var,$0):用var 全局替换整个记录$0 中所有出现的“STRING”

特殊情况:“如果你的var 中有&amp;”在行首说,那么它会与gsub 产生问题,因为&amp; 具有特殊含义并改为引用匹配的文本。

为了处理这种情况,我们必须转义&amp;,如下所示:

$ echo "STRING" | awk -v var="$var1" '{ gsub(/&/,"\\\\&",var); gsub(/STRING/,var,$0);print $0}'
&Example test here
<tag>"Hello! [world]" This line sucks!</tag>
End example file

【讨论】:

  • 谢谢@batMan。这对我有用。你是我的英雄。
  • @DomainsFeatured: :)
  • 在很多情况下这不起作用。 。例如。如果$var1 在任何地方包含&amp; 字符。
  • 更好,但如果 File1.txt 有反斜杠,例如a\m 那么它只会输出am 而不是a\m
  • @anubhava:是的,这是有道理的。您还知道其他应该处理的案件吗?
【解决方案2】:

这是一个 awk 命令,它从可能包含各种特殊字符(例如 &amp;\ 等)的文件中获取要替换的文本:

awk -v pat="STRING" 'ARGV[1] == FILENAME {
   # read replacement text from first file in arguments
   a = (a == "" ? "" : a RS) $0
   next
}
{
   # now run a loop using index function and use substr to get the replacements 
   s = ""
   while( p = index($0, pat) ) {
      s = s substr($0, 1, p-1) a
      $0 = substr($0, p+length(pat))
   }
   $0 = s $0
} 1' File1.txt <(echo "STRING")

为了能够正确处理各种特殊字符,该命令避免了任何基于正则表达式的函数。我们使用基于纯文本的函数,例如indexsubstr 等。

【讨论】:

  • 太多了!但是,非常有用!谢谢@Anubhava :-)
【解决方案3】:

问题不在于引号。您缺少“s”命令,导致sed/STRING/ 视为行地址,并将$var1 的值视为在匹配行上执行的命令。此外,$var1 具有未转义的换行符和 / 字符,这会在替换中造成麻烦。所以添加“s”,并将$var1中的相关字符转义:

var1escaped="$(echo "$var1" | sed 's@[\/&]@\\&@; $ !s/$/\\/')"
echo "STRING" | sed "s/STRING/$var1escaped/"

...但实际上,@batMan 的回答(使用awk)可能是一个更好的解决方案。

【讨论】:

  • 哎呀。我用“s”运行它,但它也不起作用。你的回答确实有效!很高兴拥有用于学习目的的背景信息。你逃脱那些其他角色的技巧是高超的。
  • @Gordon-Davisson:这真的很有帮助。你能解释一下你的第二部分,即$ !s/$/\\/'
  • @batMan 这部分转义了换行符除了文件末尾的换行符(/string)。坦率地说,它相当混乱。 echo 在打印时在变量末尾添加一个换行符;在sed 中,$ ! 地址适用于除最后一行之外的所有文件,s/$/\\/ 在行尾添加反斜杠(反斜杠加倍,因为它必须自行转义...) .请注意,$ 在这里扮演两个不同的角色——在与最后一行匹配的行地址中;在替代模式中,它匹配行尾。然后在完成所有这些之后,$( ) 删除最后一个换行符。
  • 是的,sed 中$ 的转义和含义对我来说很清楚。我现在已经了解了$ ! 在这方面的使用。谢谢戈登。这确实很有帮助。解释得很好。
猜你喜欢
  • 2021-01-21
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
  • 2013-07-19
相关资源
最近更新 更多