2011-08-23 37 views
1

这是我的问题,我写了下面这行代码来正确地格式化在目录中递归找到的文件列表。SED坏代替错误

find * | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\(\)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/" 

第二步是将此命令的输出写入脚本。虽然上面的代码具有预期的行为,但是当我尝试将其输出存储到变量时发生问题,我从行中的第一个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]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/"` 
sed -i.backup -e "s/\;Insert files here/$v\\n&/" $nsisscript 
done 

请你帮我理解两种情况之间有什么不同,以及为什么我得到这个错误?

在此先感谢!

+0

嗯......我想我自己找到了解决方案。在分隔符里面,“$”被解释为某种原因,无论是单独还是在它之前有一个反斜杠。解决方法是在每个“$”字符前加2个反斜杠。 v ='echo $ f | sed -e'/\(.*\..*\)/!d'| sed -e“s /^.*/\\$ {File} \\ $ {INST \ _FILES}&/”..... 我很乐意听到为什么会出现这种情况, 。 – Patrick

+0

与您的问题本身无关,但似乎您不知道可以更改sed的分隔符,因此您不必跳过斜线。只要选择另一个你不需要的字符,比如':':'sed's:pattern:substitution:',这将大大提高正则表达式在处理路径时的可读性 – carlpett

回答

0

嗯,我的猜测是,你在INST_FILES中下划线的转义很奇怪,因为下划线不是shell或sed中的特殊字符。当你面前“_”

我的2美分删除“\”

+0

你说的错误消失是正确的。手动改变行为并且输出结果不是我想象的那样,双反斜杠解决方案似乎可以工作 – Patrick

0

解析反引号风格的命令替换里面的错误消失是有点不可思议 - 它需要逃避的一个额外的水平(即反斜杠)以控制何时进行扩展。丑陋的解决方案:添加更多反斜杠。更好的解决方案:使用$()而不是反引号 - 它做同样的事情,但没有奇怪的解析和转义问题。

顺便说一句,你的脚本似乎有一些其他问题。首先,我不知道系统上的sed,但我熟悉的版本不会将替换中的\n解释为新行(我认为您需要),而是将其作为文字n字符。一种解决方案是在替换中包含一个字面换行符(在反斜杠前面)。

此外,循环会为每个找到的文件执行,但对于名称中没有句点的文件,第一个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]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/") 
    sed -i.backup -e "s/\;Insert files here/$v\\$nl&/" $nsisscript 
done 
+0

嗨,谢谢你的回答,我喜欢$()技巧而不是后面的引号,我认为这很麻烦。另一方面,我没有任何与换行符有关的问题,每次在文件中输入一行时,正确的后面跟着一个换行符,然后按照预期在下面插入文件。 – Patrick