正则表达式:给定一个字符串,在双引号中查找子字符串,在双引号中查找子字符串

时间:2018-03-01 14:23:56

标签: python regex

例如:

如果字符串是'“normal”script' - 输出应该显示substring normal是双引号,而子串script不是。

要从字符串中跟踪双引号子字符串,我尝试使用正则表达式:

  

r'“([^”] *)“'

我们可以使用split()方法来获取没有双引号的子字符串,但我正在寻找一种有效的方法。

下面是我尝试过的代码 - 它返回双引号的子串列表。

import re
def demo(text):      
    matches = re.findall(r'"([^"]*)"', text)
    return matches

a = demo('"normal" string "is here"')
print(a)

除了找到双引号子串之外,我还在寻找不是双引号的子串。

例如,demo('"normal" string "is here"')的输出应为:

双引号:['normal', 'is here']

非双引号:['string']

4 个答案:

答案 0 :(得分:1)

您可以在同一个正则表达式中搜索带引号和双引号的字符串。

import re

def dequote(s):
    return re.findall(r'(?:"([^"]*)")|([^"]*)', s)

print(dequote('"normal" script'))
print(dequote('another "normal" script with "extra words in it"'))

通知返回的元组列表包含带引号和非带引号的字符串。引用的字符串位于元组的第一个元素中,非引用的字符串位于第二个元素中。

如果您希望将列表分开,则将它们分开是一件简单的事情。

result = dequote('another "normal" script with "extra words in it"')

result_quoted = [t[0].strip() for t in result if t[0]]
result_unquoted = [t[1].strip() for t in result if t[1]]

print("double quoted: {}\nnot double quoted{}".format(
    result_quoted, result_unquoted))

整个计划的输出:

$ python x.py 
[('normal', ''), ('', ' script'), ('', '')]
[('', 'another '), ('normal', ''), ('', ' script with '), ('extra words in it', ''), ('', '')]
double quoted: ['normal', 'extra words in it']
not double quoted['another', 'script with']

请注意,您暗示基于re的解决方案将比基于str.split()的解决方案更快。我不相信这一点。考虑这两个解决方案:

def dequote_re(s):
    result = re.findall(r'(?:"([^"]*)")|([^"]*)', s)
    result_quoted = [t[0].strip() for t in result if t[0]]
    result_unquoted = [t[1].strip() for t in result if t[1]]
    return result_quoted, result_unquoted

def dequote_split(s):
    result = s.split('"')
    result_unquoted = [item.strip() for item in result[0::2] if item]
    result_quoted = [item.strip() for item in result[1::2] if item]
    return result_quoted, result_unquoted

他们给出了相同的答案。也许你应该运行timeit来找到哪个更快。

答案 1 :(得分:1)

使用regex模块:

>>> import re, regex
>>> s='"normal" string "is here"'

>>> re.findall(r'"([^"]*)"', s)
['normal', 'is here']

# change \w to appropriate character class as needed
>>> regex.findall(r'"[^"]*"(*SKIP)(*F)|\w+', s)
['string']

# or a workaround, remove double quoted strings first
>>> re.findall(r'\w+', re.sub(r'"([^"]*)"', '', s))
['string']

有关详细说明,请参阅Using (*SKIP)(*FAIL) to Exclude Unwanted Matches。简单地说,将(*SKIP)(*F)追加到正则表达式,你要排除并使用交替定义你需要的那些

答案 2 :(得分:0)

我知道split()是最快的replace()比正则表达式快,所以:

output = '"normal" script'.replace('"', '').split()

输出:['normal', 'script']

执行时间:3.490e-05 seconds 使用正则表达式可以获得时间0.2e-040.3e-04

答案 3 :(得分:0)

如果你有相当大的字符串,你可以使用正则表达式来计算事件并设法将它分成更小的部分(取决于你期望得到的和从哪里获得)。

看来你的子串就是单词。 对于双引号或非双引号字符串,您可以按子串分割并将其作为列表进行分割。

通过双引号或非双引号分割可能需要创建两个列表。

通过单词分词,您可以创建单个单词列表,并在输出时检查双引号。

两种情况的成本几乎相同,具体取决于您获得的字符串大小。

我建议使用https://regexr.com并尝试尽可能多地获取您可以处理的字符串。

我最好的。