SED - 用文本文件中的新文本和变量替换行号

SED - 用文本文件中的新文本和变量替换行号

我在 Bash 中使用时遇到问题sed,有人可以帮助我吗?这个sed命令运行良好...

sed命令

sed -i '3s/.*/...test_text.../g' FILE.txt

sed命令+变量

但是当我在 SED 中使用变量作为新文本、新行时,我收到错误... sed -e #expression #1, unknow option to `s'

line_number="3"
new_text="...test_text..."
FILE="FILE.txt"
sed -i "${line_number}s/.*/${new_text}/" $FILE

您能帮我解释一下,有什么问题以及我该如何/应该写这个吗?我尝试过许多其他版本,我也有其他红色主题......但我被困住了。感谢您提前提供任何帮助...

答案1

如果您的new_text变量包含斜杠,则将它们注入sed命令中会由内部表达式解析器生成语法错误sed

解决方案是使用另一个字符作为命令的分隔符s,例如逗号:

sed -i "$line_number s,.*,$new_text," "$file"

如果您的值new_text变化很大,以至于您无法可靠地选择保证不会出现在字符串中的分隔符,那么请考虑使用该c命令。可以使用c(change) 命令来替换一行。

sed -i "$line_number c \\$new_text" "$file"

该命令在 a和换行符c之后获取新文本。和\换行符\对于 GNU 来说似乎都是可选的sed。我使用\上面的允许$new_text以反斜杠开头,并且我用另一个反斜杠对其进行转义,因为我们位于双引号字符串中。

一个可移植的sed命令需要看起来像

sed "$line_number c \\
$new_text" "$file"

上面假设每个换行符$new_text前面都有一个\字符,并且作为数据一部分的任何文字反斜杠都被转义为\\


您也可以使用awk.下面,我使用 GNUawk来启用就地编辑:

text=$new_text awk -i inplace -v lineno="$line_number" \
    'NR == lineno { print ENVIRON["text"]; next }; 1' "$file"

除了 GNU 之外awk,这还假设您的新文本位于 中$new_text,行号位于 中$line_number,并且文件的路径名位于 中$file

新文本通过环境变量传递text到代码中awk,而行号则传递给命令行上的内部awk变量。lineno当找到给定的行号时,代码输出text环境变量的值,而不是打印当前行。

以这种方式使用 GNUawk对 的值没有特殊限制$new_text

示例(awk我的系统上的 GNU 称为gawk):

$ cat file.txt
Line 1
Line 2
Line 3
$ new_text='hello world'
$ line_number=2
$ file=./file.txt
$ text=$new_text gawk -i inplace -v lineno="$line_number" \
    'NR == lineno { print ENVIRON["text"]; next }; 1' "$file"
$ cat file.txt
Line 1
hello world
Line 3

答案2

如果您按照上面的方式输入变量和命令,您将看到没有错误。问题在于 的真实内容new_text。我猜它包含像这样的斜杠new_text=usr/bin。然后将变量替换后,你会得到

sed -i "3s/.*/usr/bin/" FILE.txt

因此该行被替换为usr,并sed继续解释命令的标志s并找到bof bin,这不是合法的选项。

如果您知道 的合法字符范围new_text,则只需选择该范围之外的字符作为分隔符,例如

sed -i "${line_number}s~.*~${new_text}~" $FILE

相关内容