Bash 使用可能包含斜杠的任意变量进行sed
我尝试以以下方式使用sed:Bash 使用可能包含斜杠的任意变量进行sed,bash,shell,sed,Bash,Shell,Sed,我尝试以以下方式使用sed: VAR=`echo $STRING | sed s/$TOKEN/$REPLACEMENT/` 不幸的是,我遇到了一个$REPLACEMENT可能包含斜杠的情况。这会导致bash抱怨,因为它(shell)可能会将其扩展为以下内容: #given $VAR=I like bananas, $TOKEN=bananas, and $REPLACEMENT=apples/oranges VAR=`echo I like bananas | sed s/bananas/a
VAR=`echo $STRING | sed s/$TOKEN/$REPLACEMENT/`
不幸的是,我遇到了一个$REPLACEMENT可能包含斜杠的情况。这会导致bash抱怨,因为它(shell)可能会将其扩展为以下内容:
#given $VAR=I like bananas, $TOKEN=bananas, and $REPLACEMENT=apples/oranges
VAR=`echo I like bananas | sed s/bananas/apples/oranges/`
因此,现在sed被赋予了一个包含太多/(的)的无效参数。有什么好办法处理这个问题吗?这是解决办法
VAR="I like bananas"
TOKEN="bananas"
REPLACEMENT="apples/oranges"
echo $VAR |sed "s@$TOKEN@$REPLACEMENT@"
I like apples/oranges
这是解决办法
VAR="I like bananas"
TOKEN="bananas"
REPLACEMENT="apples/oranges"
echo $VAR |sed "s@$TOKEN@$REPLACEMENT@"
I like apples/oranges
您可以使用任何您喜欢的分隔符
“s!$TOKEN!$REPLACEMENT!”
和“s%$TOKEN%$REPLACEMENT%”
是流行的替代方案
当然,在一般情况下,如果输入可以包含任何字符,那么就回到原点。您可以切换到一种不会如此轻率地混合代码和数据的语言。。。事实上,包括外壳本身
echo "${VAR/$TOKEN/$REPLACEMENT}"
(这是一个Bash扩展。它在其他一些shell中可用,但在经典的Bourne shell中不可用。)您可以使用任何您喜欢的分隔符
“s!$TOKEN!$REPLACEMENT!”
和“s%$TOKEN%$REPLACEMENT%”
是流行的替代方案
当然,在一般情况下,如果输入可以包含任何字符,那么就回到原点。您可以切换到一种不会如此轻率地混合代码和数据的语言。。。事实上,包括外壳本身
echo "${VAR/$TOKEN/$REPLACEMENT}"
(不过,这是一个Bash扩展。它在其他一些shell中可用,但在经典的Bourne shell中不可用。)您不能可靠地使用sed进行此操作,因为:
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
}')
您无法可靠地使用sed进行此操作,因为:
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
}')
您应该用括号替换旧的和过时的背面tic
$(…)
示例:VAR=$(echo$STRING | sed s/$TOKEN/$REPLACEMENT/)
可能的重复项比这更糟糕。如果$TOKEN包含RE元字符(
,*
,等等),那么sed也将对它们进行评估。这就是你想要的吗?你应该用括号替换旧的和过时的背面tic$(…)
例如:VAR=$(echo$STRING | sed s/$TOKEN/$REPLACEMENT/)
可能的重复比这更糟糕。如果$TOKEN包含RE元字符(
,*
,等等),那么sed也将对它们进行评估。这就是您想要的吗?另一个好的选择是不可打印的ascii控制字符,它们不太可能出现在字符串中:printf-v foo的\x01%s\x01%s\x01的“搜索字符串”replacsestring;echo“$string”| sed-e“$foo”
@这是另一个有趣的想法,但我不敢推荐,因为它肯定会在各种sed
实现中崩溃。我对此表示怀疑。这既违反了POSIX,而且在C中实现起来比简单地允许它更困难。至少在OSX上,我无法让它工作,尽管障碍是printf
似乎不想接受\x01
格式的控制字符。使用文字控件—一个字符—允许我解决这个问题。但无论如何,很难想出完全可移植的东西(这不会比简单地使用Perl更复杂)。另一个好的选择是不可打印的ascii控制字符,它们特别不可能出现在字符串中:printf-vfoo's\x01%s\x01%s\x01's“searchstring”“replacestring”;echo“$string”| sed-e“$foo”
@这是另一个有趣的想法,但我不敢推荐,因为它肯定会在各种sed
实现中崩溃。我对此表示怀疑。这既违反了POSIX,而且在C中实现起来比简单地允许它更困难。至少在OSX上,我无法让它工作,尽管障碍是printf
似乎不想接受\x01
格式的控制字符。使用文字控件—一个字符—允许我解决这个问题。但是无论如何,很难想出完全可移植的东西(这不会比简单地使用Perl更复杂)。