【问题标题】:Python Regex: Ignore Escaped CharacterPython 正则表达式:忽略转义字符
【发布时间】:2011-12-08 17:54:25
【问题描述】:

好的,我目前正在使用 Python 的正则表达式库将以下字符串拆分为以分号分隔的字段组。

'key1:"this is a test phrase"; key2:"this is another test phrase"; key3:"ok this is a gotcha\; but you should get it";'

正则表达式:\s*([^;]+[^\\])\s*;

我目前正在使用上面的 pcre,它工作正常,直到遇到 key3 上面提到的短语之一中包含转义分号的情况。

如何修改此表达式以仅在非转义分号上拆分?

【问题讨论】:

  • 当您尝试上面示例中的\; 时发生了什么?似乎在那之后它应该无法匹配。您的模式中的 [^\\] 是尝试解决此问题的方法,还是除了处理 \; 之外还有其他意义吗?
  • 引用的字符串可能包含转义的引号吗?即key:" \" "; 并且引用的字符串可能包含非转义分号吗?即key:" ; ";?
  • 贾斯汀,这是针对此问题的尝试解决方法。前两组被正确解析,但奇数(最后)组最终只是'但你应该得到它';',在转义分号之前切掉块。
  • Ridgerunner,字符串中的分号和引号必须转义。

标签: python regex pcre


【解决方案1】:

此版本的基本版本是您要忽略任何以反斜杠开头的 ;,而不管其他任何内容。这个比较简单:

\s*([^;]*[^;\\]);

如果您希望将输入中的 转义 反斜杠视为文字,这将变得棘手。例如:

"You may want to split here\\;"
"But not here\;"

如果您想考虑这一点,试试这个(已编辑)

\s*((?:[^;\\]|\\.)+);

为什么这么复杂?因为如果允许转义的反斜杠,那么您必须考虑这样的事情:

"0 slashes; 2 slashes\\; 5 slashes\\\\\; 6 slashes\\\\\\;"

每对双反斜杠都将被视为文字\。这意味着 ; 只有在它之前有 奇数 个反斜杠时才会被转义。所以上面的输入会这样分组:

#1: '0 slashes'
#2: '2 slashes\'
#3: '5 slashes\\; 6 slashes\\\'

因此图案的不同部分:

\s*            #Whitespace
((?:
    [^;\\]     #One character that's not ; or \
  |            #Or...
    \\.        #A backslash followed by any character, even ; or another backslash
)+);           #Repeated one or more times, followed by ;

在反斜杠之后要求一个字符可确保第二个字符始终正确转义,即使它是另一个反斜杠。

【讨论】:

  • 我们真的需要负面的看法还是我错过了什么?
  • @Abhijit - 如果你没有区分\;\\;,那么你不需要一个(因此我的第二个模式没有一个)。如果您想将\\; 视为文字反斜杠并在; 上正常拆分,那么我看不到任何其他方法。
  • @JohnDoe - 所以负面的后视是允许的,但如果它们像我的最后一个模式一样是可变长度的,则不允许。在这种情况下,我想不出一个正则表达式可以检测输入中的转义反斜杠。
  • @JohnDoe - 我想我说得太早了。检查编辑的图案。
【解决方案2】:

如果字符串可能包含分号和转义引号(或转义任何内容),我建议解析每个有效的key:"value"; 序列。像这样:

import re
s = r'''
    key1:"this is a test phrase";
    key2:"this is another test phrase";
    key3:"ok this is a gotcha\; but you should get it";
    key4:"String with \" escaped quote";
    key5:"String with ; unescaped semi-colon";
    key6:"String with \\; escaped-escape before semi-colon";
    '''
result = re.findall(r'\w+:"[^"\\]*(?:\\.[^"\\]*)*";', s)
print (result)

请注意,这会正确处理双引号字符串中的任何转义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2010-12-22
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    相关资源
    最近更新 更多