【问题标题】:Find indexes of unquoted words in a string using `re.finditer()` method使用 `re.finditer()` 方法查找字符串中未引用单词的索引
【发布时间】:2021-02-10 23:29:56
【问题描述】:

我正在尝试在字符串中查找未加引号的单词的位置(索引),但我的所有测试均未成功。

对于字符串:string='foo "bar" baz'我想得到

(0, 3)   # This for foo
(10, 13) # This for baz
# I'd like to skip the quoted "bar"

但是,我尝试的每个正则表达式都包含引用的 'bar' 或其一部分:

string='foo "bar" baz'
_RE_UNQUOTED_VALUES = re.compile(r"([^\"']\w+[^\"'])")
print([m.span() for m in _RE_UNQUOTED_VALUES.finditer(string)])

输出:[(0, 4), (5, 8), (9, 13)]

或使用:

_RE_UNQUOTED_VALUES = re.compile(r"(?!(\"|'))\w+(?!(\"|'))")
# Outputs [(0, 3), (5, 7), (10, 13)]

这不能用正则表达式实现吗?我是否误解了finditer() 的工作原理?

【问题讨论】:

    标签: python regex tokenize


    【解决方案1】:

    你可以使用

    import re
    string="foo 'bar' baz"
    ms = re.finditer(r"""\b(?<!['"])\w+\b(?!['"])""", string)
    print([(x.start(), x.end()) for x in ms])
    # => [(0, 3), (10, 13)]
    

    请参阅Python demo

    \b(?&lt;!['"])\w+\b(?!['"]) 正则表达式首先匹配一个单词边界,然后 (?&lt;!') 否定查找失败匹配,如果有一个 '/" 字符紧邻左侧,然后匹配一个或多个单词字符,检查如果右侧有一个 '/" 字符,则再次单词边界位置和 (?!['"]) 否定前瞻失败匹配。

    请参阅regex demo

    【讨论】:

      【解决方案2】:

      你也可以使用:

      import re
      
      string='foo "bar" baz'
      _RE_UNQUOTED_VALUES = re.compile(r"(?<!['\"\w])\w+(?![\"'\w])")
      print([m.span() for m in _RE_UNQUOTED_VALUES.finditer(string)])
      

      输出:

      [(0, 3), (10, 13)]
      

      在这种情况下,使用\w 以及否定环视中的引号字符会强制引擎仅匹配未被引号包围的整个单词。

      【讨论】:

        【解决方案3】:

        .index 代替正则表达式怎么样?这种方式更具可读性和可扩展性。例如:

        strstr=lambda s, sub: (s.index(sub), s.index(sub)+len(sub))
        strstr('foo "bar" baz', 'foo')
        # (0, 3)
        strstr('foo "bar" baz', 'baz')
        # (10, 13)
        

        但是,如果你不知道输入并且需要使用正则表达式,@Wiktor 的答案会更好。

        【讨论】:

          猜你喜欢
          • 2018-11-20
          • 1970-01-01
          • 1970-01-01
          • 2021-06-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-03
          • 1970-01-01
          相关资源
          最近更新 更多