我目前正在开发一个自定义源补丁程序,我遇到了用另一个替换字符串的麻烦,包括换行符。
例如,我想删除此模式:
\n/* @patch[...]*/
为了得到这个......:
this.is = code ;
/* @patch beta
blah blah
*/
if (!this.is) return 0 ;
/* @patch end */
......对此:
this.is = code ;
if (!this.is) return 0 ;
不这个:
this.is = code ;
<- newline
if (!this.is) return 0 ;
<- newline
使用shell脚本,我正在使用sed
命令来执行我想要的操作:
sed -e "s|\/\* @patch.*\*\/||g" $file > $file"_2"
这很好用,但新行仍然存在。
这种方式不起作用,因为sed
无法解析换行符:
sed -e "s|\n\/\* @patch.*\*\/||g" $file > $file"_2"
这种方法都不起作用:How can I replace a newline (\n) using sed?,也不是tr
(同一主题上的第二个答案)。
你能解决这个问题吗?即使是沉重的,性能也不重要。
P.S。 :我正在开发一个Web应用程序,在这种情况下是JavaScript文件。在Mac OS X Yosemite下,但无论我使用什么系统,它似乎都是所有bash用户的常见问题。
我找到了另一个使用Node.js的解决方案,用于那些遇到Awk版本问题的人:
node -e "console.log(process.argv[1].replace(/[\n\r]\/\* @patch([\s\S]*?)\*\//mg, ''))" "`cat $filepath`"
答案 0 :(得分:2)
sed用于单独行的简单替换,对于你应该使用awk的任何其他内容:
$ awk -v RS='^$' -v ORS= '{gsub(/[*][/]/,"\0"); gsub(/\n[/][*] @patch[^\0]+\0/,""); gsub(/\0/,"*/")} 1' file
this.is = code ;
if (!this.is) return 0 ;
上面使用GNU awk for multi-char RS将整个文件作为一个单独的字符串读取(其他人要求你只需逐行构建字符串并在END部分处理)并依赖于你的文件不包含任何字符串NUL(\0
)个字符。
第一个gsub()
将每个*/
更改为一个字符(一个NUL),因此第二个gsub()
可以在括号表达式中将其作为所需正则表达式的一部分,然后是第三个{ {1}}将剩余的NUL恢复为gsub()
。
非gawk你需要建立字符串:
*/
听起来你的awk需要转义括号表达式中的awk '{rec = rec $0 RS} END{gsub(/[*][/]/,"\0",rec); gsub(/\n[/][*] @patch[^\0]+\0/,"",rec); gsub(/\0/,"*/",rec); printf "%s",rec}' file
,所以它不会将它们视为RE的终止字符:
/
如果你的awk不喜欢NUL字符,那么使用一些控制字符,例如(其中每个awk '{rec = rec $0 RS} END{gsub(/[*][\/]/,"\0",rec); gsub(/\n[\/][*] @patch[^\0]+\0/,"",rec); gsub(/\0/,"*/",rec); printf "%s",rec}' file
是一个文字控件-C字符):
^C
或使用awk用于分隔数组索引的预定义awk '{rec = rec $0 RS} END{gsub(/[*][\/]/,"^C",rec); gsub(/\n[\/][*] @patch[^^C]+^C/,"",rec); gsub("^C","*/",rec); printf "%s",rec}' file
控制字符(注意,您现在需要将REs中的反斜杠加倍,这些字符串是字符串与SUBSEP的串联,因为它们现在是动态的正则表达式而不是常量正则表达式,有关详细信息,请参阅http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps:
SUBSEP