怎么用正则去匹配尖括号之外的所有空格?

2016-10-12 17:11:41 +08:00
 wlee1991
<img src="699.jpg" alt="" width="620" height="350" title="" align="" />   太难了。多行汉字。多行汉字。多行汉字。
	  太难了。  <img src="699.jpg" alt="" width="620" height="350" title="" align="" />
多行汉字。多行汉字。多行汉字。多行汉字。
  怎么办。呵呵
2038 次点击
所在节点    正则表达式
13 条回复
soratadori
2016-10-12 18:52:09 +08:00
零宽断言
aploium
2016-10-12 22:59:00 +08:00
```python
# Python 3
impor re
# text = 你上面的那段
result = re.sub(r"""(?<!<)([^>]*?)( )(?![^<]*>)""", "\g<1>+", text)
print(result)
```

上面这段正则把尖括号之外的空格替换为加号(+)
能力有限, 不知道怎么把第一个捕获括号变成非捕获的. 因为 python 要求 look-behind 必须是 fixed-width pattern
结果为:
```
<img src="699.jpg" alt="" width="620" height="350" title="" align="" />+++太难了。多行汉字。多行汉字。多行汉字。
++太难了。++<img src="699.jpg" alt="" width="620" height="350" title="" align="" />
多行汉字。多行汉字。多行汉字。多行汉字。
++怎么办。呵呵
```
注意其中有一行的开头是 Tab, 不是空格, 所以没替换掉
aploium
2016-10-12 22:59:17 +08:00
为什么不支持 markdown - -
sutra
2016-10-12 23:00:35 +08:00
public class Regex {

public static void main(String[] args) {
String s = " 太难了。多行汉字。\n 多行汉字。多行汉字。 太难了。 <img src=\"699.jpg\" alt=\"\" width=\"620\" height=\"350\" title=\"\" align=\"\" /> 太难了。多行汉字。\n 多行汉字。多行汉字。 太难了。 <img src=\"699.jpg\" alt=\"\" width=\"620\" height=\"350\" title=\"\" align=\"\" /> 多行汉字。\n 多行汉字。多行汉字。多行汉字。";
s = s.replaceAll("([ ]+)(?![^<]*>|[^<>]*</)", "");
System.out.println(s);
}

}
sutra
2016-10-12 23:06:59 +08:00
上面这个漏了一种 case <tag></tag>

package com.oxerr.sandbox;

public class Regex {

public static void main(String[] args) {
String s = " 太难了。多行汉字。\n 多行汉字。多行汉字。 太难了。 <br /> <span> aa </span> <img src=\"699.jpg\" alt=\"\" width=\"620\" height=\"350\" title=\"\" align=\"\" /> 太难了。多行汉字。\n 多行汉字。多行汉字。 太难了。 <img src=\"699.jpg\" alt=\"\" width=\"620\" height=\"350\" title=\"\" align=\"\" /> 多行汉字。\n 多行汉字。多行汉字。多行汉字。";
s = s.replaceAll("([ ]+)(?![^<]*>)", "");
System.out.println(s);
}

}
aploium
2016-10-12 23:16:18 +08:00
@sutra 还有一种恶心的 case:
```
<tag/> 我在 tag 外面 > > ←这是两个不规范的→尖括号
```
msg7086
2016-10-13 02:44:26 +08:00
只有我会去 capture >和<之间的内容然后把 capture 到的文字拿去抹空格么……
msg7086
2016-10-13 02:54:25 +08:00
s.gsub(/>[^<]+</) {|ss| ss.delete(' ')}
wlee1991
2016-10-13 10:32:01 +08:00
@msg7086 最终还是要获得去掉空格之后的所有内容,包括尖括号里面的;
nicoljiang
2016-10-13 11:18:48 +08:00
比较严禁的处理思路大概是类似这样的吧:

第一种方案:
1. 最小匹配所有的<.*?>,把每个匹配出来的段落存到 hash 中,并把他们替换成相应 key 作为代号;
2. 去所有空格;
3. 把所有在第一步中替换成的 key 代号变回相应的<.*?>中。

第二种方案:
1. 最小匹配所有的<.*?>,并把匹配内容的空格替换成某个代号;
2. 把全文所有空格去掉;
3. 再把第一步中的代号替换回空格。

这样执行效率可能略低,但比较准确。
wlee1991
2016-10-13 21:46:37 +08:00
@nicoljiang 谢谢,后来确实也是这么做了。
msg7086
2016-10-15 08:34:12 +08:00
@wlee1991 是啊,返回的不就是所有内容么。
Capture 是做替换啊。替换完了以后还是所有的内容。
msg7086
2016-10-15 08:35:44 +08:00
@nicoljiang 很多正则函数都支持一边替换一边处理的。比如 PHP 里:
http://php.net/manual/zh/function.preg-replace-callback.php

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/312276

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX