使用正则表达式折叠除空白行之外的空白

问题描述:

过去我不止一次地想过格式化文本块的问题,以便将所有空白运行“折叠”为一个空格,但段落应该是保存 - 意味着所有空行的运行都会折叠为单个空行,但不会折叠为空格。使用正则表达式折叠除空白行之外的空白

空白行当然是两个行尾字符(通常是回车符或换行符或两者),没有任何中间非空白字符。 (虽然可能有其他空格,例如空格或制表符)。

这确实是一个很常见的问题,虽然不难解决,但我总是对我的解决方案不满意,因为这些解决方案缺乏优雅或留下漏洞。当然,有一个优雅的表达方式来做到这一点。

由于我至少希望在Perl,Vim和JavaScript中使用它,所以我将它放到了所有的正则表达式中。这是我最近在node.js中做的懒惰尝试,这个漏洞显然是魔术词。这也可能是非常典型的,我用::

text = text.replace(/\r?\n(?:\s*\r?\n)+/g, '_SomeMagicWord_'); 
text = text.replace(/\s\s+/gm, ' '); 
text = text.replace(/_SomeMagicWord_/g, '\r\n\r\n'); 

如果我的解释并不清楚应该从这次改造不理想的解决方案:

富酒吧巴兹
弗雷德·巴尼威尔玛


一二三

这样:

富酒吧巴兹弗雷德·巴尼威尔玛

一二三

(!当心在线路的两端也尾随空白)

的sed:

sed -n 'H;$g;$s/[^\n]\n[^\n]/ /g;$s/\n\n\n*/\n\n/g;$s/ */ /g;$s/^\n//;$p' FILENAME 

Perl:

perl -ne '$a.=$_;END{$_=$a;s/ */ /g;s/[^\n]\n[^\n]/ /g;s/\n\n\n*/\n\n/g;print}' FILENAME 
+0

目前我在Windows上并没有访问sed,我也不知道sed,所以我不能自己解析。我会尝试一个Perl,但如果单线程是Windows友好的... – hippietrail 2013-02-08 13:04:38

+0

在Windows上,Pe​​rl需要使用'''而不是''',即使有这种变化,我正在失去al段落格式化(双空行) 。 – hippietrail 2013-02-08 13:08:47

+1

在你的例子中,你将四行换行变成了一个换行符,你能为我提供一个更具描述性的例子输入和输出吗?(也有段落格式)当我测试时,我的两个程序都可以 – protist 2013-02-08 13:12:28

我刚刚就这个问题再次提出。这一次,我使用Node.js的,我觉得我想出了一个漂亮的表现力的解决方案:

txt = txt.replace(/\s+/g, function (ws) { 
    return /\n.*\n/.test(ws) ? '\n\n' : ' '; 
}); 

txt = txt.replace(/(^(|\n\n)|(|\n\n)$)/g, ''); 

,第一部分考虑了文本的空白和检查的每个运行,如果有在其中至少两个换行符。如果是这样,它会崩溃到段落中断(连续两次换行而没有其他)。否则它会崩溃到一个空间。

第二部分修剪文本开始和结尾的任何剩余空白,在这一点上,每个空白仅可能是单个空格或一对换行符。 (我唯一的限制是由JavaScript的\s强加的,它不符合所有的Unicode空格代码点;并且可选地输出MS样式的换行符,\r\n而不是\n。)