bash Sed 错误:“替代模式中未转义的换行符”和“替代命令中的错误标志”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13930074/
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 error: 'unescaped newline inside substitute pattern' and 'bad flag in substitute command'
提问by kimimaro
Question:
题:
I am new in sed,so when I excute following code in shell:
我是 sed 新手,所以当我在 shell 中执行以下代码时:
sed -e "/^\s<key>CHANNEL_NAME<\/key>$/{N;s/\(^\s<string>\).+\(<\/string>$\)/test}" Info.plist > test.plist
Sed give me an error: "sed: 1: "/^\sCHANNEL_NAME<\ ...": unescaped newline inside substitute pattern"
sed 给我一个错误:"sed: 1: "/^\sCHANNEL_NAME<\ ...": unscaped newline inside替代模式"
My Question: What does "unescaped newline inside substitute pattern" exactly mean?
我的问题:“替代模式中未转义的换行符”究竟是什么意思?
The Info.plist file is like this:
Info.plist 文件是这样的:
...
<key>CHANNEL_NAME</key>
<string>App Store</string>
...
I am appreciate everyone could answer the question, thanks!
非常感谢大家能回答这个问题,谢谢!
Anwser:
答案:
Thanks @potong @dogbane @Beta ! : )
谢谢@potong @dogbane @Beta!:)
Because it is a Cocoa plist, so here's my finally solution:
因为它是 Cocoa plist,所以这是我的最终解决方案:
sed '/<key>CHANNEL_NAME<\/key>/{N;s/\(<string>\).*\(<\/string>\)/test/;}' Info.plist > test.plist
Tips:
提示:
- I got two error during my process to solve the problem. Put them here:
- sed: 1: "/^\sCHANNEL_NAME<\ ...": unescaped newline inside substitute pattern
- sed: 1: "/CHANNEL_NAME</ke ...": bad flag in substitute command: '}'
- I make so many mistakes in the first code.
- haven't escaped the '+'
- should end with 2/}"
- acturally should end with 2/;}" (I miss a ';', so I got the second error in Tips 1)
- user 'n' or 'N' both works for me.
- Probably because of on Mac, the '.+' (even if I escaped) not work, so have to change it as @potong said, '..*'
- 在解决问题的过程中,我遇到了两个错误。把它们放在这里:
- sed: 1: "/^\sCHANNEL_NAME<\ ...": 替代模式内未转义的换行符
- sed: 1: "/CHANNEL_NAME</ke ...": 替代命令中的错误标志:'}'
- 我在第一个代码中犯了很多错误。
- 没有逃脱“+”
- 应该以 2/} 结尾"
- 实际上应该以 2/;}" 结尾(我错过了一个 ';',所以我在提示 1 中遇到了第二个错误)
- 用户 'n' 或 'N' 都适用于我。
- 可能是因为在 Mac 上,“.+”(即使我逃脱了)不起作用,所以必须像@potong 所说的那样更改它,“..*”
Any good advice to approve the code is welcome, thanks all the following guys again!
欢迎任何批准代码的好建议,再次感谢以下所有人!
回答by potong
This might work for you (GNU sed):
这可能对你有用(GNU sed):
sed -e '/^\s*<key>CHANNEL_NAME<\/key>$/{n;s/^\(\s*<string>\).\+\(<\/string>\)$/test/}' Info.plist > test.plist
N.B. You should allow for whitespace (^\s*) at the beginning of a line and print the matched line before comparing the start of the next line for the substitution command i.e. use ninstead of N.
注意您应该允许^\s*在一行的开头有空格 ( ) 并在比较下一行的开头之前打印匹配的行以获取替换命令,即使用n而不是N.
Or:
或者:
sed -e '/^ *<key>CHANNEL_NAME<\/key>$/!b' -e 'n' -e 's/^\( *<string>\)..*\(<\/string>\)$/test/' Info.plist > test.plist
回答by Ed Morton
Since you said you're just learning sed: sed is an excellent tool for simple substitutions on a single line but for anything else just use awk.
既然你说你只是在学习 sed:sed 是一个很好的工具,可以在一行中进行简单的替换,但对于其他任何事情,只需使用 awk。
Here's a GNU awk solution (you can cram it onto one line if you like):
这是一个 GNU awk 解决方案(如果你愿意,你可以把它塞进一行):
$ cat file
...
foo
<key>CHANNEL_NAME</key>
<string>App Store</string>
...
$
$ awk '
found { $ awk '
found { awk '
found { ##代码##=gensub(/(<string>).*(<\/string>)/,"\1" rep "\2",""); found=0 }
/<key>CHANNEL_NAME<\/key>/ { found=1; rep=prev }
{ print ##代码##; prev=##代码## }
' file
...
foo
<key>CHANNEL_NAME</key>
<string>foo</string>
...
=gensub(/(<string>).*(<\/string>)/,"\1test\2",""); found=0 }
/<key>CHANNEL_NAME<\/key>/ { found=1 }
{ print NR, ##代码## }
' file
1 ...
2 foo
3 <key>CHANNEL_NAME</key>
4 <string>test</string>
5 ...
=gensub(/(<string>).*(<\/string>)/,"\1test\2",""); found=0 }
/<key>CHANNEL_NAME<\/key>/ { found=1 }
{ print ##代码## }
' file
...
foo
<key>CHANNEL_NAME</key>
<string>test</string>
...
It doesn't LOOK much different from the sed solution, but just try modifying the sed solution to do anythingadditional e.g. add line numbers to the output:
它看起来与 sed 解决方案没有太大不同,但只需尝试修改 sed 解决方案以执行任何其他操作,例如向输出添加行号:
##代码##or replace the text between "string"s with the contents of the line before CHANNEL_NAME instead of the hard-coded "test":
或者用 CHANNEL_NAME 之前的行的内容替换“string”之间的文本,而不是硬编码的“test”:
##代码##and you'll find you need a whole other solution, probably involving a nightmarish concoction of single letters and punctuation marks, whereas with awk it's a simple tweak to enhance your starting solution.
并且您会发现您需要一个完整的其他解决方案,可能涉及单个字母和标点符号的噩梦般的组合,而使用 awk,这是一个简单的调整,可以增强您的初始解决方案。

