Shell删除包含换行符的字符串

时间:2015-06-23 15:34:41

标签: regex bash shell sed

我目前正在开发一个自定义源补丁程序,我遇到了用另一个替换字符串的麻烦,包括换行符。

例如,我想删除此模式:

\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`"

1 个答案:

答案 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