bash SED 坏替换错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7157921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SED bad substitution error
提问by Patrick
Here's my problem, I have written the following line of code to format properly a list of files found recursively in a directory.
这是我的问题,我编写了以下代码行来正确格式化在目录中递归找到的文件列表。
find * | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/${File} ${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\//" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}$]*\.[a-zA-Z0-9]*\)/ /"
The second step is to write the output of this command in a script. While the code above has the expected behavior, the problem occurs when I try to store its output to a variable, I get a bad substitution error from the first sed command in the line.
第二步是将这个命令的输出写在一个脚本中。虽然上面的代码具有预期的行为,但当我尝试将其输出存储到变量时会出现问题,我从该行中的第一个 sed 命令中得到一个错误的替换错误。
#!/bin/bash
nsisscript=myscript.sh
FILES=*
for f in $(find $FILES); do
v=`echo $f | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/${File} ${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\//" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}$]*\.[a-zA-Z0-9]*\)/ /"`
sed -i.backup -e "s/\;Insert files here/$v\n&/" $nsisscript
done
Could you please help me understand what the difference is between the two cases and why I get this error ?
您能否帮助我理解这两种情况之间的区别以及为什么会出现此错误?
Thanks in advance!
提前致谢!
回答by neuro
Well my guess was that your escaping of underscore in INST_FILES is strange as underscore is not a special character in shell nor in sed. The error disappear when you delete the '\' before '_'
好吧,我的猜测是您在 INST_FILES 中转义下划线很奇怪,因为下划线在 shell 和 sed 中都不是特殊字符。当您删除 '_' 之前的 '\' 时,错误消失
my 2 cents
我的 2 美分
回答by Gordon Davisson
Parsing inside of backquote-style command substitution is a bit weird -- it requires an extra level of escaping (i.e. backslashes) to control when expansions take place. Ugly solution: add more backslashes. Better solution: use $()instead of backquotes -- it does the same thing, but without the weird parsing and escaping issues.
解析反引号样式的命令替换内部有点奇怪——它需要额外的转义级别(即反斜杠)来控制何时进行扩展。丑陋的解决方案:添加更多反斜杠。更好的解决方案:使用$()而不是反引号——它做同样的事情,但没有奇怪的解析和转义问题。
BTW, your script seems to have some other issues. First, I don't know about the sedon your system, but the versions I'm familiar with don't interpret \nin the substitution as a newline (which I presume you want), but as a literal ncharacter. One solution is to include a literal newline in the substitution (preceded by a backslash).
顺便说一句,您的脚本似乎还有其他一些问题。首先,我不知道sed您系统上的 ,但是我熟悉的版本\n在替换中不会将换行符解释为换行符(我认为您想要),而是将其解释为文字n字符。一种解决方案是在替换中包含一个文字换行符(前面有一个反斜杠)。
Also, the loop executes for each found file, but for files that don't have a period in the name, the first sedcommand removes them, $vis empty, and you add a blank line to myscript.sh. You should either put the filtering sedcall in the forstatement, or add it as a filter to the findcommand.
此外,循环会针对每个找到的文件执行,但对于名称中没有句点的文件,第一个sed命令将删除它们,该命令$v为空,然后您将一个空行添加到 myscript.sh。您应该将过滤sed调用放在for语句中,或者将其作为过滤器添加到find命令中。
#!/bin/bash
nsisscript=myscript.sh
nl=$'\n'
FILES=*
for f in $(find $FILES -name "*.*"); do
v=$(echo $f | sed -e "s/^.*/${File} ${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\//" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}$]*\.[a-zA-Z0-9]*\)/ /")
sed -i.backup -e "s/\;Insert files here/$v\$nl&/" $nsisscript
done

