我在 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
并找到b
of bin
,这不是合法的选项。
如果您知道 的合法字符范围new_text
,则只需选择该范围之外的字符作为分隔符,例如
sed -i "${line_number}s~.*~${new_text}~" $FILE