V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wlee1991
V2EX  ›  正则表达式

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

  •  
  •   wlee1991 · 2016-10-12 17:11:41 +08:00 · 2135 次点击
    这是一个创建于 2974 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <img src="699.jpg" alt="" width="620" height="350" title="" align="" />   太难了。多行汉字。多行汉字。多行汉字。
    	  太难了。  <img src="699.jpg" alt="" width="620" height="350" title="" align="" />
    多行汉字。多行汉字。多行汉字。多行汉字。
      怎么办。呵呵
    
    13 条回复    2016-10-15 08:35:44 +08:00
    soratadori
        1
    soratadori  
       2016-10-12 18:52:09 +08:00
    零宽断言
    aploium
        2
    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
        3
    aploium  
       2016-10-12 22:59:17 +08:00
    为什么不支持 markdown - -
    sutra
        4
    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
        5
    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
        6
    aploium  
       2016-10-12 23:16:18 +08:00
    @sutra 还有一种恶心的 case:
    ```
    <tag/> 我在 tag 外面 > > ←这是两个不规范的→尖括号
    ```
    msg7086
        7
    msg7086  
       2016-10-13 02:44:26 +08:00
    只有我会去 capture >和<之间的内容然后把 capture 到的文字拿去抹空格么……
    msg7086
        8
    msg7086  
       2016-10-13 02:54:25 +08:00
    s.gsub(/>[^<]+</) {|ss| ss.delete(' ')}
    wlee1991
        9
    wlee1991  
    OP
       2016-10-13 10:32:01 +08:00
    @msg7086 最终还是要获得去掉空格之后的所有内容,包括尖括号里面的;
    nicoljiang
        10
    nicoljiang  
       2016-10-13 11:18:48 +08:00
    比较严禁的处理思路大概是类似这样的吧:

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

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

    这样执行效率可能略低,但比较准确。
    wlee1991
        11
    wlee1991  
    OP
       2016-10-13 21:46:37 +08:00
    @nicoljiang 谢谢,后来确实也是这么做了。
    msg7086
        12
    msg7086  
       2016-10-15 08:34:12 +08:00
    @wlee1991 是啊,返回的不就是所有内容么。
    Capture 是做替换啊。替换完了以后还是所有的内容。
    msg7086
        13
    msg7086  
       2016-10-15 08:35:44 +08:00
    @nicoljiang 很多正则函数都支持一边替换一边处理的。比如 PHP 里:
    http://php.net/manual/zh/function.preg-replace-callback.php
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5459 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 56ms · UTC 08:14 · PVG 16:14 · LAX 00:14 · JFK 03:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.