Sed 错误:“替代模式内未转义的换行符”和“替代命令中的错误标志”
Posted
技术标签:
【中文标题】Sed 错误:“替代模式内未转义的换行符”和“替代命令中的错误标志”【英文标题】:Sed error: 'unescaped newline inside substitute pattern' and 'bad flag in substitute command' 【发布时间】:2012-12-18 09:40:32 【问题描述】:问题:
我是sed新手,所以当我在shell中执行以下代码时:
sed -e "/^\s<key>CHANNEL_NAME<\/key>$/N;s/\(^\s<string>\).+\(<\/string>$\)/\1test\2" Info.plist > test.plist
Sed 给我一个错误:“sed: 1: "/^\sCHANNEL_NAME
我的问题:“替代模式内未转义的换行符”到底是什么意思?
Info.plist 文件是这样的:
...
<key>CHANNEL_NAME</key>
<string>App Store</string>
...
感谢大家回答问题,谢谢!
回答者:
感谢@potong @dogbane @Beta! :)
因为它是一个 Cocoa plist,所以这是我的最终解决方案:
sed '/<key>CHANNEL_NAME<\/key>/N;s/\(<string>\).*\(<\/string>\)/\1test\2/;' Info.plist > test.plist
提示:
-
我在解决问题的过程中遇到了两个错误。把它们放在这里:
sed: 1: "/^\sCHANNEL_NAME
sed: 1: "/CHANNEL_NAME...": 替换命令中的错误标志:''
我在第一个代码中犯了很多错误。
没有逃脱'+'
应该以 2/" 结尾
实际上应该以 2/;" 结尾(我错过了一个 ';',所以我在提示 1 中遇到了第二个错误)
用户“n”或“N”都适用于我。
可能是因为在 Mac 上,'.+'(即使我逃脱了)不起作用,所以必须按照@potong 所说的那样更改它,'..*'
欢迎任何好的建议来批准代码,再次感谢以下所有人!
【问题讨论】:
我无法重现此错误。但是您的sed
表达式还有其他问题。您还没有逃脱 +
并且缺少一个斜杠来终止 s
命令,即它应该以 2/"
结尾。
@dogbane 非常感谢。这是一个错误的输入,但问题不是表达。恩,你的操作系统是什么? Linux 还是 Mac?
我可以重现错误(在 Mac 上),当我更正 +
并使用 2/;
终止命令时,替换工作。
【参考方案1】:
这可能对你有用(GNU sed):
sed -e '/^\s*<key>CHANNEL_NAME<\/key>$/n;s/^\(\s*<string>\).\+\(<\/string>\)$/\1test\2/' Info.plist > test.plist
注意您应该在行的开头允许空格 (^\s*
) 并在比较替换命令的下一行的开头之前打印匹配的行,即使用 n
而不是 N
。
或者:
sed -e '/^ *<key>CHANNEL_NAME<\/key>$/!b' -e 'n' -e 's/^\( *<string>\)..*\(<\/string>\)$/\1test\2/' Info.plist > test.plist
【讨论】:
我尝试了您的建议,但仍然无法做到。我认为这可能是因为 Mac OS,但不确定。感谢所有的保存 @kimimaro 我添加了一个更通用的解决方案(删除了\s
和\+
元字符)。但是,这不考虑标签。
你的回答很有用!因为我的上下文是一个可可plist,所以可能最接近的答案是我自己的问题之后的答案,但你已经解决了我的问题。谢谢!【参考方案2】:
既然您说您只是在学习 sed:sed 是一个出色的工具,可以在单行上进行简单替换,但对于其他任何事情,只需使用 awk。
这是一个 GNU awk 解决方案(如果你愿意,你可以把它塞进一行):
$ cat file
...
foo
<key>CHANNEL_NAME</key>
<string>App Store</string>
...
$
$ awk '
found $0=gensub(/(<string>).*(<\/string>)/,"\\1test\\2",""); found=0
/<key>CHANNEL_NAME<\/key>/ found=1
print $0
' file
...
foo
<key>CHANNEL_NAME</key>
<string>test</string>
...
它看起来与 sed 解决方案没有太大区别,但只需尝试修改 sed 解决方案来做 任何事情 额外的,例如在输出中添加行号:
$ awk '
found $0=gensub(/(<string>).*(<\/string>)/,"\\1test\\2",""); found=0
/<key>CHANNEL_NAME<\/key>/ found=1
print NR, $0
' file
1 ...
2 foo
3 <key>CHANNEL_NAME</key>
4 <string>test</string>
5 ...
或将“字符串”之间的文本替换为 CHANNEL_NAME 之前的行的内容,而不是硬编码的“测试”:
awk '
found $0=gensub(/(<string>).*(<\/string>)/,"\\1" rep "\\2",""); found=0
/<key>CHANNEL_NAME<\/key>/ found=1; rep=prev
print $0; prev=$0
' file
...
foo
<key>CHANNEL_NAME</key>
<string>foo</string>
...
你会发现你需要一个完全不同的解决方案,可能涉及单个字母和标点符号的噩梦般的混合,而使用 awk 是一个简单的调整来增强你的初始解决方案。
【讨论】:
以上是关于Sed 错误:“替代模式内未转义的换行符”和“替代命令中的错误标志”的主要内容,如果未能解决你的问题,请参考以下文章