Sed和逃避单引号

时间:2012-12-26 16:23:25

标签: shell sed ksh

我遇到了sed和单引号的问题

我有一个这样的字符串:

-cmd af -i 3 -a

我想将此字符串更改为

-cmd 'af -i 3 -a'

现在我正在使用它:

字符串存储在buff变量

buff=$(echo $buff | sed -r "s/cmd /CMD '/g")"'"

它回应了好-cmd 'af -i 3 -a'

然后我用buff作为参数调用一个函数,在用ksh -x执行脚本时我可以看到调用是NOK

+ buff=$'-CMD \'af -i 3 -a \''
+ echo -CMD $'\'af' -i 3 -a $'\''
-CMD 'af -i 3 -a' #this is the echo
+ functionTest -CMD $'\'af' -i 3 -a $'\''

因此它总会给我

-CMD $'\'af' -i 3 -a $'\''

所以基本上我的单引号似乎被解释为$'\''

我不知道为什么,我尝试了很多东西,例如转义字符,但它给了我完全相同的结果,即使使用\x27

3 个答案:

答案 0 :(得分:2)

你怎么看到奇数球的结果?

你所得到的是原始的(Mac OS X上的sed不支持-r,但使用的正则表达式不需要非标准的GNU扩展选项{{1无论如何):

-r

我怀疑你的问题不在变换中,而在于你查看结果的方式。


ksh test

$ buff1="-cmd af -i 3 -a"
$ buff2=$(echo $buff1 | sed -e "s/cmd /CMD '/g")"'"
$ echo $buff2
-CMD 'af -i 3 -a'
$

输出正确;跟踪有点令人困惑,但与你所展示的相同。

Osiris JL: cat so14043243.sh buff1="-cmd af -i 3 -a" buff2=$(echo $buff1 | sed -e "s/cmd /CMD '/g")"'" echo $buff2 echo "$buff2" Osiris JL: ksh -x so14043243.sh + buff1='-cmd af -i 3 -a' + sed -e $'s/cmd /CMD \'/g' + echo -cmd af -i 3 -a + buff2=$'-CMD \'af -i 3 -a\'' + echo -CMD $'\'af' -i 3 $'-a\'' -CMD 'af -i 3 -a' + echo $'-CMD \'af -i 3 -a\'' -CMD 'af -i 3 -a' Osiris JL: 输出的额外努力是有充分理由的;它消除了输出的歧义,以便您可以确切地确定什么是什么,如果您能够很好地阅读它。此外,您可以复制'{'}在-x之后的行并且运行它并再次获得完全相同的结果。旧的Bourne shell有一个+选项,它不会像这样做字符映射,它可能会导致混淆,你当然无法可靠地复制'n'paste跟踪输出来再次执行命令。

关键点在于结果 - 回声 - 是你想要和期望的,所以你在烦恼(无论如何)。但我同意,一开始可能会让人感到困惑。

答案 1 :(得分:2)

它对我也很好。但是没有必要sed; bash builtins可以做到这一点:

$ buff='-cmd af -i 3 -a'
$ buff=${buff/cmd /CMD \'}\'
$ echo $buff
-CMD 'af -i 3 -a'

答案 2 :(得分:0)

我认为@gniourf_gniourf关于在变量中存储字符串的初步评论基本上是正确的(即使你只是试图存储命令参数);见BashFAQ #050: I'm trying to put a command in a variable, but the complex cases always fail!

现在,你有两个困惑。首先,您误解了-x模式正在打印的内容。它不会打印您正在运行的命令的参数,它会打印一个将传递相同参数的命令 。在这种情况下,一些参数包括单引号,因此它给出了一个带引号和转义的字符串,在引用删除之后,将产生实际传递的相同参数。例如,其中一个参数是'af,因此-x模式将其显示为$'\'af'

其次,看起来你正试图在变量中嵌入单引号,这样你就可以将几个单词作为单个参数传递给functionTest(即你试图运行等价的functionTest -CMD 'af -i 3 -a'). If I'm right about what you're trying to do, you're doing it fundamentally wrong. When the shell parses a command line, it interprets quotes and escapes, *then* substitutes variables. It'll go back and split the replaced variables into words, but it will not go back and pay attention to quotes and escapes in the substituted text. So when it replaces $ buff with - CMD'af -i 3 -a'`,它将它分成5个参数:“-CMD”,“'af”,“ - i”,“3”和“-a” “。请注意,单引号被视为第二个和第五个参数的一部分,而不是包含一个长参数:

$ buff="-CMD 'af -i 3 -a'"
$ printargs $buff
Got 5 arguments:
  «-CMD»
  «'af»
  «-i»
  «3»
  «-a'»

为了存储多个参数而不会产生这种混淆,你需要使用一个数组(再次参见@ gniourf_gniourf的评论和BashFAQ #050):

$ buff=(-CMD 'af -i 3 -a')
$ printargs "${buff[@]}"
Got 2 arguments:
  «-CMD»
  «af -i 3 -a»
顺便说一下,如果你想复制它,你需要printargs。这是一个非常简单的shell脚本,我写的是为了澄清这样的情况:

#!/bin/sh

echo "Got $# arguments:"
for arg; do
        echo "  «${arg}»"
done
相关问题