我想在java中使用多行字符串,所以我寻求一个简单的预处理器,将C风格的多行转换为单行,文字为'\ n'。
在:
System.out.println("convert trailing backslashes\
this is on another line\
\
\
above are two blank lines\
But don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");
后:
System.out.println("convert trailing backslashes\nthis is on another line\n\n\nabove are two blank lines\nBut don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");
我认为sed
会做得很好,但是sed是基于行的,所以替换'\'和它后面的换行符(有效加入两行)在sed中并不是很自然。我将sredden79's oneliner改编为以下内容 - 它有效,但它很聪明,但不清楚:
sed ':a { $!N; s/\\\n/\\n/; ta }'
替补是escaped literal backslash
,newline
escaped literal backslash
,n
。 :a
是标签,如果替代品找到匹配,则ta
为goto标签; $
表示最后一行,而$!
则相反(即所有行,但最后一行)。 N
表示将下一行附加到模式空间(从而使\n
字符可见。)
编辑这里是保持编译器错误行号等准确的变体:它将每个扩展行转换为"..."+\n
(并正确处理字符串的第一行和最后一行):
sed ':a { $!N; s/\\\n/\\n"+\n"/; ta }'
,并提供:
System.out.println("convert trailing backslashes\n"+
"this is on another line\n"+
"\n"+
"\n"+
"above are two blank lines\n"+
"But don't convert non-trailing backslashes, like: \"\t\" and \'\\\'");
EDIT 实际上,最好使用Perl / Python风格的多行,它在一行上以特殊代码开头和结尾(对于python,我认为是“”)。 / p>
是否有更简单,更清晰,更清晰的方式(可能不使用sed)?
答案 0 :(得分:5)
是否有更简单,更安全,更清晰的方式。
忘记预处理器,忍受限制,抱怨它(以便它可以在Java 7或8中修复)和use an IDE to ease the pain。
其他替代方案(我认为太麻烦了,但仍然比搞乱编译过程更好):
答案 1 :(得分:3)
perl one-liner:
perl -0777 -pe 's/\\\n/\\n/g'
这将读取stdin或在命令行上以它命名的文件,并将输出写入stdout。
如果你使用的是支持过滤的编辑器,比如vi或emacs,只需通过上面的命令过滤你的文字就可以了:
如果您使用的是Windows,则必须担心\r
:
C:\> perl -0777 -pe "s/\\\r?\n/\\n/g"
虽然我认为win32 Perl会处理\r
本身,所以这可能是不必要的。
-0777
选项是定义行或记录分隔符的-0
(这是零)选项的特例。在这种情况下,这意味着我们不需要任何分隔符,因此将整个文件作为单个字符串读取。
-pe
选项是-p
(逐行处理并打印结果)和-e
(下一个参数是要执行的程序的一行)的组合)
答案 2 :(得分:1)
你要求的perl脚本。
while (<>) {
chomp;
print $_;
if (/\\$/) {
print "n";
} else {
print "\n";
}
}
答案 3 :(得分:0)
sed 's/\x5c\x5c$/\x22\x5c\x5cn\x22/'
反斜杠和双引号的十六进制分别是\ x5c和\ x22 - 它需要被转义,因此\ x5c加倍并且$ anchors到行的末尾。
根据OP评论再次更新:
sed "{:a;N;\$!b a};s/\x5c\x5c\n/\x5c\x5cn/g"
:a创建一个标签,N在模式空间附加一条线,b a分支回标签:a除了最后一行$!
全部加载后 - 单行替换将替换所有出现的换行符\ n用文字&#39; \ n&#39;使用十六进制ascii代码\ x5c作为反斜杠。