V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
1oscar
V2EX  ›  Python

正则大神,一个正则问题

  •  
  •   1oscar · 2015-06-16 18:34:29 +08:00 · 5276 次点击
    这是一个创建于 3450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    字符串1: Tyrsovo Nám., 252 63 布拉格, 捷克共和国
    字符串2: Via Augusta 127, 8006 巴塞罗那, 西班牙
    字符串3: Victoria Regina Square 11-12, 1210 布鲁塞尔 - Botanique, 比利时

    希望得出各个字符串的城市名,比如字符串1是,布拉格,字符串2是, 巴塞罗那,字符串3是布鲁塞尔等等

    后面的字符串可能还会更加的不规则,但是唯一的规律就是都有两处中文,城市与国家,要求取出城市名

    求指导

    24 条回复    2015-06-18 00:27:18 +08:00
    oott123
        1
    oott123  
       2015-06-16 18:45:04 +08:00
    难道不是用逗号切开然后匹配中文就行了么……
    iyangyuan
        2
    iyangyuan  
       2015-06-16 18:50:04 +08:00 via iPhone
    .*([\u2E80-\uFE4F]+).*,.*[\u2E80-\uFE4F]+.*
    手机打的,没测,仅供参考
    chopper
        3
    chopper  
       2015-06-16 18:54:18 +08:00
    中文 233333,不知道ascii对应值,随便找了个
    [\u4e00-\u9fa5]+(?=.*,)
    funagi
        4
    funagi  
       2015-06-16 19:05:24 +08:00
    ```
    Python 2.7.6 (default, Mar 22 2014, 22:59:38)
    [GCC 4.8.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = u'''Tyrsovo Nám., 252 63 布拉格, 捷克共和国
    ... Via Augusta 127, 8006 巴塞罗那, 西班牙
    ... Victoria Regina Square 11-12, 1210 布鲁塞尔 - Botanique, 比利时'''
    >>> p = re.compile(u'([\u2E80-\u9FFF]+)')
    >>> for line in s.split('\n'):
    ... m = p.search(line)
    ... if m:
    ... print(m.group(1))
    ...
    布拉格
    巴塞罗那
    布鲁塞尔
    >>>
    ```
    lilydjwg
        5
    lilydjwg  
       2015-06-16 19:14:35 +08:00
    你们这些用正则的都不知道有个东西叫 \p{Han} 么。当然,PCRE 和 Python 的 regex 第三方库才支持。
    Biwood
        6
    Biwood  
       2015-06-16 19:17:48 +08:00
    第一部 /\d\s.*(?=,\s)/,去除数字+空格开头,,以逗号结尾的部分;
    第二部[\u4e00-\u9fa5],取出中文;

    应该有办法一步完成的,我再研究研究
    Biwood
        7
    Biwood  
       2015-06-16 19:18:37 +08:00
    打错字了,两步都是“取出”
    heiybb
        8
    heiybb  
       2015-06-16 19:30:36 +08:00 via Android
    picasso250
        9
    picasso250  
       2015-06-16 19:53:45 +08:00
    [^,]+,[\d ]+([^,]+)

    解释:
    匹配第一个逗号之前的内容.
    匹配数字
    匹配城市名
    Septembers
        10
    Septembers  
       2015-06-16 20:27:23 +08:00 via Android
    这是CSV格式啊
    keepsome
        11
    keepsome  
       2015-06-16 20:32:52 +08:00
    适用于一行仅两段中文
    [^\x{4e00}-\x{9fa5}]+([\x{4e00}-\x{9fa5}]+)[^\x{4e00}-\x{9fa5}]+[\x{4e00}-\x{9fa5}]+\s+
    全部替换成$1
    最后一行加个换行或者手动提取就行
    notepad++实测成功
    msg7086
        12
    msg7086  
       2015-06-16 20:33:02 +08:00
    @Septembers 并不是吧。
    keepsome
        13
    keepsome  
       2015-06-16 20:36:24 +08:00
    [^\x{4e00}-\x{9fa5}]+([\x{4e00}-\x{9fa5}]+)[^\x{4e00}-\x{9fa5}]+[\x{4e00}-\x{9fa5}]+.*\s+
    修订版,为了防止后一段中文之后还有字符
    其他一致,全部替换成$1
    最后一行加个换行或者手动提取
    1oscar
        14
    1oscar  
    OP
       2015-06-16 22:12:46 +08:00
    @funagi Thank you!
    ElvisZhu
        15
    ElvisZhu  
       2015-06-16 22:37:49 +08:00
    ^[^,]+,[ 0-9]*([^0-9 ,]+).*
    取\1
    leavic
        16
    leavic  
       2015-06-17 00:35:06 +08:00
    先用逗号split一下吧,中文我还真不知道怎么搞,得查unicode代码
    tntasdf
        17
    tntasdf  
       2015-06-17 09:08:18 +08:00
    // PHP

    $str="Tyrsovo Nám., 252 63 布拉格, 捷克共和国
    Via Augusta 127, 8006 巴塞罗那, 西班牙
    Victoria Regina Square 11-12, 1210 布鲁塞尔 - Botanique, 比利时";

    preg_match_all('/([^\x00-\x80]+?)(,|\s-)/',$str,$mts); // 更不规则的,改括号2的正则

    print_r($mts); // $mts[1] 就是了


    事实上不需要拘泥于一个正则搞定,可以先做字符串处理。正则规则写得越复杂,效率越慢。
    tntasdf
        18
    tntasdf  
       2015-06-17 09:25:26 +08:00
    写的是php , python不懂多少 。 主要看正则,大致是可以移植的。PHP中需要[^\x00-\x80]来匹配中文,python的话应该是其他, 另外就是非贪婪模式了。
    dallaslu
        19
    dallaslu  
       2015-06-17 09:28:42 +08:00
    ,[\d\s]+(.*?)[,\s]
    dallaslu
        20
    dallaslu  
       2015-06-17 09:29:43 +08:00
    tsingyi
        21
    tsingyi  
       2015-06-17 09:48:57 +08:00
    如果只是取出第一个中文字符串的话可以用正则表达式的断言:

    (?!=[\u4E00-\u9FBF]+)[\u4E00-\u9FBF]+(?=\s|,)

    (?!=[\u4E00-\u9FBF]+) 确保之前没有中文字符
    (?=\s|,)确保字符后为逗号或空格
    asj
        22
    asj  
       2015-06-17 10:09:14 +08:00
    用excel打开,复制列
    ToughGuy
        23
    ToughGuy  
       2015-06-17 15:30:44 +08:00
    import re

    s = 'xxxxxx'

    re.findall(r'\d+ ([^\d ,]+)[, ]', s)
    wuhx
        24
    wuhx  
       2015-06-18 00:27:18 +08:00
    上一个scala的版本

    val str = """字符串1: Tyrsovo Nám., 252 63 布拉格, 捷克共和国
    字符串2: Via Augusta 127, 8006 巴塞罗那, 西班牙
    字符串3: Victoria Regina Square 11-12, 1210 布鲁塞尔 - Botanique, 比利时"""

    val pat = """(\p{IsHan}+)""".r

    for(lines <- str.split("\n")) {
    val m = pat.findAllMatchIn(lines)
    println(m.drop(1).next())
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1034 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:15 · PVG 06:15 · LAX 14:15 · JFK 17:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.