[英]Use a variable as replacement in bash sed command
我在 Ubuntu 上使用sed
命令来替换内容。
这个初始命令来自这里。
sed -i '$ s/$/ /replacement/' "$DIR./result/doc.md"
但是,正如您所看到的,我在替换中使用了斜线。 斜线导致命令抛出:
sed: -e 表达式 #1, char 9: `s' 的未知选项
此外,我的替换存储在一个变量中。
因此,由于斜杠,以下内容将不起作用:
sed -i "$ s/$/ $1/" "$DIR./result/doc.md"
正如此处和一式两份所述,我应该使用另一个分隔符。 如果我尝试@
:
sed -i "$ s@$@ $1@" "$DIR./result/doc.md"
它给出了错误:
sed:-e 表达式 #1,字符 42:未终止的 `s' 命令
我的问题是:
如何在此命令中使用变量以及除/
之外的其他分隔符?
sed
; perl
和awk
允许更强大的方法。 sed
不允许变量从代码带外传递,因此它们总是需要转义。 使用没有这种限制的语言,您的代码始终有效,无论您的数据包含什么字符。
perl
以下内容摘自BashFAQ #21 :
inplace_replace() {
local search=$1; shift; local replace=$1; shift
in="$search" out="$replace" perl -pi -e 's/\Q$ENV{"in"}/$ENV{"out"}/g' "$@"
}
inplace_replace '@' "replacement" "$DIR/result/doc.md"
awk
...或者,使用awk
进行流式替换,并使用 shell 函数进行文件替换:
# usage as in: echo "in should instead be out" | gsub_literal "in" "out"
gsub_literal() {
local search=$1 replace=$2
awk -v s="${search//\\/\\\\}" -v r="${rep//\\/\\\\}" 'BEGIN {l=length(s)} {o="";while (i=index($0, s)) {o=o substr($0,1,i-1) r; $0=substr($0,i+l)} print o $0}'
}
# usage as in: inplace_replace "in" "out" /path/to/file1 /path/to/file2 ...
inplace_replace() {
local search=$1 replace=$2 retval=0; shift; shift
for file; do
tempfile=$(mktemp "$file.XXXXXX") || { retval |= $?; continue; }
if gsub_literal "$search" "$replace" <"$file" >"$tempfile"; then
mv -- "$tempfile" "$file" || (( retval |= $? ))
else
rm -f -- "$tempfile" || (( retval |= $? ))
fi
done
}
特尔;博士:
尝试:
sed -i '$ s@$@ '"$1"'@' "$DIR./result/doc.md"
长版:
让我们从您的原始代码开始:
sed -i '$ s/$/ /replacement/' "$DIR./result/doc.md"
让我们将它与您引用的代码进行比较:
sed -i '$ s/$/abc/' file.txt
我们可以看到它们并不完全匹配。 我看到您正确地进行了此替换:
file.txt --> "$DIR./result/doc.md"
看起来不错(尽管我对 $DIR 之后的 . 有疑问)。 但是,其他替换看起来不太好:
abc --> /replacement
您实际上引入了另一个分隔符 /。 但是,如果我们用“@”替换分隔符,我们会得到:
sed -i '$ s@$@ /replacement@' "$DIR./result/doc.md"
我认为上述内容在 sed/bash 中完全有效。 $@
不会被 shell 替换,因为它是单引号的。 $DIR
变量将被 shell 插入,因为它是双引号的。
看看你的尝试之一:
sed -i "$ s@$@ $1@" "$DIR./result/doc.md"
由于双引号中 $@ 的 shell 插值,您将遇到问题。 让我们通过用单引号替换(但保留 $1 不加引号)来更正:
sed -i '$ s@$@ '"$1"'@' "$DIR./result/doc.md"
注意'"$1"'。 我不得不用 '' 包围 $1 以基本上取消周围的单引号。 但是后来我用双引号将 $1 括起来,这样我们就可以保护字符串免受空格的影响。
使用shell 参数扩展向变量中的斜杠添加转义:
$ cat file
foo
bar
baz
$ set -- ' /repl'
$ sed "s/$/$1/" file
sed: 1: "s/$/ /repl/": bad flag in substitute command: 'r'
$ sed "s/$/${1//\//\\\/}/" file
foo /repl
bar /repl
baz /repl
这是倾斜牙签的怪物,但它有助于改变这一点:
sed "s/$/ /repl/"
进入
sed "s/$/ \/repl/"
相同的技术可用于您选择作为 sed s///
分隔符的任何内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.