0

我在使用 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

4

3 回答 3

2

您如何看待奇数球的结果?

你所拥有的是原始的(sed在 Mac OS X 上不支持-r,但使用的正则表达式不需要非标准的 GNU 扩展选项-r):

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

我怀疑您的问题不在于转换,而在于您查看结果的方式。


ksh测试

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;它消除了输出的歧义,以便您可以准确地确定什么是什么,如果您可以很好地阅读它。此外,您可以在之后复制'n'粘贴该行+并运行它并再次获得完全相同的结果。旧的 Bourne shell 有一个-x选项,它没有像这样进行字符映射,这可能会导致混乱,而且您当然不能可靠地复制'n'粘贴跟踪输出以再次执行命令。

关键是结果——回响的东西——是你想要和期待的,所以你无所事事(当它发生时)。但我同意,一开始可能会令人困惑。

于 2012-12-26T16:29:57.783 回答
2

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

$ buff='-cmd af -i 3 -a'
$ buff=${buff/cmd /CMD \'}\'
$ echo $buff
-CMD 'af -i 3 -a'
于 2012-12-26T16:32:51.773 回答
0

我认为@gniourf_gniourf 关于将字符串存储在变量中的初始评论基本上是正确的(即使您只是尝试存储命令参数);请参阅BashFAQ #050:我正在尝试将命令放入变量中,但复杂的情况总是失败!.

现在,你有两个困惑。首先是您误解了-x打印的模式。它不会打印您正在运行的命令的参数,它会打印一个将传递相同 arguments的命令。在这种情况下,一些参数包含单引号,因此它给出了一个带引号和转义的字符串,在去除引号后,将产生与实际传递的参数相同的参数。例如,参数之一是'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
于 2012-12-26T18:59:02.490 回答