执行sed命令时出错

时间:2015-11-24 05:40:39

标签: shell sed cygwin

我正在尝试使用命令执行脚本:

sed -i "USER/c\export USER=${signumid}" .bashrc

sed -i "DEVENVHOME=$/c\export DEVENVHOME=${DEVENVHOME:-/home/${signumid}/CPM_WORKAREA/devenv.x}" .bashrc
 

我想将USER中的字符串“.bashrc”替换为export USER=${signumid},其中$signumid变量通过Cygwin提示提供。同样,我想在DEVENVHOME=$文件中用export DEVENVHOME=${DEVENVHOME:-/home/${signumid}/CPM_WORKAREA/devenv.x}替换字符串.bashrc,其中$signumid变量通过Cygwin提示符提供。

但我在Cygwin termminal上遇到以下错误。:

 sed: -e expression #1, char 1: unknown command: `U'
 sed: -e expression #1, char 3: extra characters after command

1 个答案:

答案 0 :(得分:0)

sed脚本的一般语法是一系列地址 命令 参数语句(由换行符或分号分隔) 。最常见的命令s替换命令,带有一个空的地址,因此我们可以假设这就是您要在此处使用的内容。您似乎试图插入一个shell变量$signumid,这会给这个展示添加一些复杂功能。

如果你的字符串只是静态文本,那么使用单引号是有意义的;然后,shell根本不会更改引号内的文本。 s命令的一般语法是s/regex/replacement/,其中作为参数分隔符的斜杠只是一个占位符,我们很快就会看到。

sed -i 's/.*USER.*/export USER=you/
    s% DEVENVHOME=\$%export DEVENVHOME=${DEVENVHOME:-/home/you/CPM_WORKAREA/devenv.x}%' .bashrc

这将找到包含USER的任何行,并用export USER=you替换整行;然后找到任何包含DEVENVHOME=$的行(前面有空格,以及字面的美元字符),并用长字符串替换匹配的表达式。因为替换字符串在内部使用斜杠,我们使用不同的正则表达式分隔符% - 或者,我们可以反斜杠 - 转义不是分隔符的斜杠,但正如我们将看到的,当我们添加以下内容时,它很快变得难以维持捻。因为美元符号作为正则表达式中的“行尾”元字符具有重要意义,所以我们反斜杠 - 逃避它。

我在假设它只是对c\语法的误解的假设中忽略了sed。如果它很重要,你希望用它完成什么? c\export不是有效的Bash命令,所以你可能意味着别的东西,但我不知道是什么。

现在,要将shell变量signumid的值插入到替换中,我们不能使用单引号,因为那些禁止插值。您已经正确地尝试使用双引号(在您编辑的问题中),但这意味着我们必须进行一些额外的更改。在双引号内,反斜杠由shell处理,因此我们需要将所有反斜杠加倍,或者找到替代结构。幸运的是,对于我们来说,唯一的反斜杠是\$,它可以等效地表示为[$],所以让我们改用这种符号。此外,在替换字符串中需要文字美元符号的情况下,我们反斜杠 - 转义它以防止shell处理它。

sed -i "s/.*USER.*/export USER=$signumid/
    s% DEVENVHOME=[$]%export DEVENVHOME=\${DEVENVHOME:-/home/$signumid/CPM_WORKAREA/devenv.x}%" .bashrc

等效,您可以在脚本部分周围使用单引号,这些部分应该不受外壳影响,然后在需要插值的部分周围放置一个相邻的双引号字符串,例如

'un$touched*by$(the!shell)'"$signumid"'more$[complex]!stuff'

这个最后的剧本仍然依赖于一些幸运的或者可能相当不幸的猜测,关于你真正想要的东西。在第一行,我将USER更改为与整行匹配的正则表达式 - 也许这不是您想要的?另一方面,第二行做出相反的假设,只是因为你可以看到变化 - 它只替换我们匹配的实际文本。可能需要更改其中一个。

最后,请注意两个单独的sed命令是如何混合到一个脚本中的。许多新手没有意识到sed是一种脚本语言,它接受脚本中的任意数量的命令,并简单地将其视为具有有趣语法的“替换”程序。

混淆的另一个常见原因是评估顺序。 shell甚至在sed开始执行之前处理双引号字符串,因此如果引号中有错误,您可以轻松地在sed脚本中产生语法错误,这会导致相当无法提供信息的错误消息(因为sed在错误消息中告诉你的是基于shell的替换后脚本的样子。例如,如果signumid包含斜杠,则会产生语法错误,因为sed会将这些视为s///命令的终止分隔符。一个简单的解决方法是切换到signumid的值不会出现的分隔符。