我正在尝试以以下方式使用 sed:
VAR=`echo $STRING | sed s/$TOKEN/$REPLACEMENT/`
不幸的是,我遇到了$REPLACEMENT可能包含斜杠的情况。这会导致 bash 抱怨,因为它(外壳)可能会将其扩展为如下所示的内容:
#given $VAR=I like bananas, $TOKEN=bananas, and $REPLACEMENT=apples/oranges
VAR=`echo I like bananas | sed s/bananas/apples/oranges/`
所以现在 sed 被赋予了一个带有太多/'s 的无效参数。有什么好办法可以处理吗?
您可以使用任何您喜欢的分隔符。 "s!$TOKEN!$REPLACEMENT!"
和"s%$TOKEN%$REPLACEMENT%"
是流行的选择。
当然,在一般情况下,如果输入可以包含任何字符,那么您又回到了原点。你可以切换到一种不会如此轻率地混合代码和数据的语言......事实上,包括外壳本身;
echo "${VAR/$TOKEN/$REPLACEMENT}"
(不过,这是一个 Bash 扩展。它有其他一些外壳,但不是经典的伯恩外壳。
修复
VAR="I like bananas"
TOKEN="bananas"
REPLACEMENT="apples/oranges"
echo $VAR |sed "s@$TOKEN@$REPLACEMENT@"
I like apples/oranges
您不能可靠地将 sed 用于此目的,因为:
- 您通常找不到保证不会在任何$TOKEN或$REPLACEMENT字符串中,以及
- sed 无法搜索字符串 - 它总是搜索正则表达式和因此,$TOKEN中的任何 RE 元字符都将被评估为这样,并且您无法可靠地实现代码来转义它们(尽管许多人们尝试过)。
所以,只需使用 awk:
VAR=$(echo "$STRING" | awk -v t="$TOKEN" -v r="$REPLACEMENT" 'idx=index($0,t) {$0 = substr($0,1,idx-1) r substr($0,idx+length(t))} 1')
这绝对适用于 3 个字符串中的任何一个字符,除了 $STRING 中的换行符。
如果没有echo
它也将在$STRING中处理换行符:
VAR=$(awk -v s="$STRING" -v t="$TOKEN" -v r="$REPLACEMENT" '
BEGIN {
if (idx = index(s,t))
s = substr(s,1,idx-1) r substr(s,idx+length(t))
print s
}')