执行sed命令时出错 [英] Error while executing sed command

查看:2526
本文介绍了执行sed命令时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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



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



但我在Cygwin终端上收到以下错误:

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

解决方案

sed 脚本的一般语法是一系列 参数语句(以换行符或分号分隔)。最常见的命令 s 替换命令,带有一个空的地址,因此我们可以假设你想在这里使用什么。你似乎试图插入一个shell变量 $ signumid ,这会给这个exposition添加一点复杂性。



如果你的字符串只是静态文本,使用单引号是有意义的;然后,shell不会改变引号内的文本。 s 命令的一般语法是 s / regex / replacement / ,其中斜杠作为参数分隔符只是一个

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

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



我忽略了 c \ 在你的尝试中,假设它只是一个误解 sed 语法。如果它是重要的,你希望用它完成什么? c\export 不是一个有效的Bash命令,所以你可能是别的什么,但我不能猜测是什么。



现在,要插入shell变量 signumid 的值替换,我们不能使用单引号,因为那些禁止插值。您已正确尝试使用双引号(在您编辑的问题中),但这意味着我们必须进行一些其他更改。在双引号内,反斜杠由shell处理,因此我们需要将所有反斜杠加倍,或者找到替代结构。幸运的是,唯一的反斜线是 \ $ ,等价地表示为 [$] 切换到这个符号。另外,如果在替换字符串中需要一个字符的美元符号,我们反斜杠转换它以防止shell处理它。

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

同样,您可以在脚本的各个部分使用单引号这意味着不被shell触及,然后在需要插值的部分周围放置一个相邻的双引号字符串,例如

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


b $ b

这个最后的脚本仍然基于一些幸运的或者可能是相当不幸的猜测你实际想要什么。在第一行,我改变了 USER 到一个正则表达式匹配整行 - 也许这不是你想要的?另一方面,第二行做出相反的假设,只是为了看到变化 - 它只替换了我们匹配的实际文本。可能一个或另一个需要改变。



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



另一个常见的混乱来源是评估顺序。即使在 sed 开始执行之前,shell也会处理双引号字符串,因此如果在引用中出现错误,您可以轻松地在 sed 脚本,这会导致错误信息,因为 sed 在错误消息中告诉你,壳的取代基)。例如,如果 signumid 包含斜杠,则会产生语法错误,因为 sed 会将其视为终止分隔符 s /// 命令。一个简单的解决方法是切换到 signumid 中不出现的分隔符。


I am trying to execute script with commands:

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

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

I want to replace the line with string "USER" in .bashrc with export USER=${signumid} where $signumid variable is being provided through Cygwin prompt. Similarly I want to replace line with string DEVENVHOME=$ with export DEVENVHOME=${DEVENVHOME:-/home/${signumid}/CPM_WORKAREA/devenv.x} in .bashrc file, where $signumid variable is provided through Cygwin prompt.

But I am getting following errors on Cygwin termminal.:

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

解决方案

The general syntax of a sed script is a sequence of address command arguments statements (separated by newline or semicolon). The most common command is the s substitution command, with an empty address, so we can perhaps assume that that is what you want to use here. You seem to be attempting to interpolate a shell variable $signumid which adds a bit of a complication to this exposition.

If your strings were simply static text, it would make sense to use single quotes; then, the shell does not change the text within the quotes at all. The general syntax of the s command is s/regex/replacement/ where the slash as the argument separator is just a placeholder, as we shall soon see.

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

This will find any line with USER and substitute the entire line with export USER=you; then find any line which contains DEVENVHOME=$ (with a space before, and a literal dollar character) and replace the matched expression with the long string. Because the substitution string uses slashes internally, we use a different regex separator % -- alternatively, we could backslash-escape the slashes which are not separators, but as we shall see, that quickly becomes untenable when we add the following twist. Because the dollar sign has significance as the "end of line" metacharacter in regular expressions, we backslash-escape it.

I have ignored the c\ in your attempt on the assumption that it is simply a misunderstanding of sed syntax. If it is significant, what do you hope to accomplish with it? c\export is not a valid Bash command, so you probably mean something else, but I cannot guess what.

Now, to interpolate the value of the shell variable signumid into the replacement, we cannot use single quotes, because those inhibit interpolation. You have correctly attempted to use double quotes instead (in your edited question), but that means we have to make some additional changes. Inside double quotes, backslashes are processed by the shell, so we need to double all backslashes, or find alternative constructs. Fortunately for us, the only backslash is in \$ which can equivalently be expressed as [$], so let's switch to that notation instead. Also, where a literal dollar sign is wanted in the replacement string, we backslash-escape it in order to prevent the shell from processing it.

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

Equivalenty, you could use single quotes around the parts of the script which are meant to be untouched by the shell, and then put an adjacent double-quoted string around the parts which need interpolation, like

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

This final script still rests on a number of lucky or perhaps rather unlucky guesses about what you actually want. On the first line, I have changed just USER to a regular expression which matches the entire line -- maybe that's not what you want? On the other hand, the second line makes the opposite assumption, just so you can see the variations -- it only replaces the actual text we matched. Probably one or the other needs to be changed.

Finally, notice how the two separate sed commands have been conflated into a single script. Many newcomers do not realize that sed is a scripting language which accepts an arbitrary number of commands in a script, and simply treat it as a "replace" program with a funny syntax.

Another common source of confusion is the evaluation order. The shell processes the double-quoted string even before sed starts to execute, so if you have mistakes in the quoting, you can easily produce syntax errors in the sed script which lead to rather uninformative error messages (because what sed tells you in the error message is based on what the script looks like after the shell's substutions). For example, if signumid contains slashes, it will produce syntax errors, because sed will see those as terminating separators for the s/// command. An easy workaround is to switch to a separator which does not occur in the value of signumid.

这篇关于执行sed命令时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆