我们如何使用 sed 将特定行替换为字符串变量?

我们如何使用 sed 将特定行替换为字符串变量?

举例来说,我有一个file.txt包含 3 行的内容:

hello
hello
hello

我有一个名为 的变量line=1和一个变量 string substitute=hello1。我想line用名为 的新字符串变量替换变量描述的行中的字符串substitute

最终的更改将files.txt如下所示:

hello1
hello
hello

我将如何使用sed来做到这一点?或者awk?如果这就是你想要的,只要我可以输入可以在 while 循环中更改的变量。

答案1

perl

export line substitute
perl -pi -e '$_ = $ENV{substitute} . "\n" if $. == $ENV{line}' file.txt

与 GNU 相同awk

export line substitute
gawk -i /usr/share/awk/inplace.awk '
  NR == ENVIRON["line"] {$0 = ENVIRON["substitute"]}
  {print}' file.txt

在这里使用sed并不理想,即使对于那些支持类似 perl-i选项的选项也是如此,因为我们需要对它的值进行一些后处理,$substitute如果它可能包含反斜杠、&命令s分隔符或换行符。看如何确保插入到“sed”替换中的字符串转义所有元字符详细信息。

gawk不使用-i inplaceas尝试首先从当前工作目录gawk加载inplace扩展(asinplace或),有人可能已经在其中植入了恶意软件。随系统提供的扩展inplace.awk的路径可能会有所不同,请参阅输出inplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答案2

假设line >0并且总是整数,你可以这样做:

<infile head -n$(($line-1)); printf '%s\n' "$substitute"; tail -n +$(($line+1)) infile

请注意,如果 line_number > file's_number_of_lines,这会将$substitute值附加到文件末尾$line

答案3

如果没有更多信息,以下awk程序应该可以工作:

awk -v where="$line" -v what="$substitute" 'FNR==where {print what; next} 1' file.txt
  • 它将把 shell 变量$line和导入$substituteawk变量where和中what
  • 处理文件时,默认情况下它会简单地打印当前行(看似偏离1规则块之外的行{ ... })。
  • 当每个文件的行计数器FNR等于存储在 中的行号时where,我们将打印替换字符串what,并跳到下一个输入行执行。

请注意,这awk不会就地编辑文件,因此您必须在满意后重定向输出并重命名结果文件。或者,对于足够新的 GNU 版本awk,您可以使用该-i inplace选项就地修改文件。

笔记(正如 αГsнιη/Stéphane Chazelas/Ed Morton 所指出的)如果您的substitute字符串包含文字,上面的代码将显示出不稳定的行为\,因为此方法会扩展转义序列。在这种情况下,awkStéphane Chazelas 的答案中基于 - 的替代解决方案可以导出变量并引用它,这样就ENVIRON["substitute"]可以解决问题(请参阅这个答案了解更多信息)。

答案4

$   line=1 substitute=hello1
$ sed -nf - <<eof file 
  $line r $(t=$(mktemp);printf '%s\n' "$substitute" > "$t";echo "$t")
  $line!p
eof

我们使用heredoc来传递sed代码。 sed 代码正在读取文件并将 jts 内容放置在标准输出上,并通过该-n选项抑制原始行。

相关内容