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

时间:2013-02-08 12:32:48

标签: regex whitespace text-formatting blank-line

过去不止一次我想知道格式化文本块的问题,以便所有空格的运行都“折叠”到一个空格中,除了段落应该被保存 - 意味着所有空白行的运行被折叠成单个空白行,但没有折叠成一个空格。

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

这肯定是一个非常普遍的问题,虽然不难解决,但我总是对我的解决方案感到不满,因为我的解决方案缺乏优雅或留下漏洞。当然,有一种优雅的表达方式来做到这一点。

因为我想至少在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');

如果我的解释不清楚,它应该改变:

  

foo bar baz
  弗雷德巴尼威尔马
  
  
  一二三

到此:

  foo bar baz fred barney wilma
  
  一二三

(注意线末端的尾随空格!)

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我刚刚再次遇到这个问题。这次我使用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 。)