Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中获取第一个管道和第二个管道之间的数据_Python_Regex - Fatal编程技术网

在python中获取第一个管道和第二个管道之间的数据

在python中获取第一个管道和第二个管道之间的数据,python,regex,Python,Regex,这是我的样本数据 78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193 我想得到结果 Indonesia 目前我正在对字符串使用split并访问该值。但是我想用正则表达式 需要注意的一些条件: 数据可能是空的 数据将不包含管道(|) 我想使用regex而不是split,因为我认为regex更有效。我希望它尽可能高效的原因是源文件是70gb 编辑: 这是我将使用的全部代码 def main(argv): mylist =

这是我的样本数据

78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193
我想得到结果

Indonesia
目前我正在对字符串使用split并访问该值。但是我想用正则表达式

需要注意的一些条件: 数据可能是空的 数据将不包含管道(|)

我想使用regex而不是split,因为我认为regex更有效。我希望它尽可能高效的原因是源文件是70gb

编辑:

这是我将使用的全部代码

def main(argv):
    mylist = set();
    input_file = open("test.txt", 'r')

    for row in input_file:
        rowsplit = row.split("|");

        if rowsplit[1] !='':
            if rowsplit[1] in mylist:
                filename= "bby_"+rowsplit[1]+".dat";
                existingFile=open(filename,'a')
                existingFile.write(row);
                existingFile.close()
            else:
                mylist.add(rowsplit[1])
                filename= "bby_"+rowsplit[1]+".dat";
                newFile = open(filename,'a')
                newFile.write(row);
                newFile.close();
        else:
            print "Empty"
    print mylist
我只是对我现在应该使用的答案感到困惑:(


我只想让这段代码快一点。就这样。

我想你可以在以下网址找到答案:


Joschua(回答上述链接问题的用户)进行了测试,使用正则表达式效率更高。

这一个相当简单:如果您知道第一个子句始终是一个数字(或空),您可以锚定到前面

^\d*\|(\w+?)?\|
这将匹配行前面的0个或多个数字,后跟一个literal
字符,后跟子句1,该子句将包含一个非贪婪匹配字(不带空格),如果不存在,则不包含任何内容,后跟literal
字符


性能正则表达式很快就会失败,而非贪婪匹配和锚定是至关重要的。

使用这个正则表达式就可以抓住第一个单词

re.search(r'^[^a-zA-Z]*([a-zA-Z]+)', S).group(1)

这将为您提供介于第一管道和第二管道之间的信息:

 re.search(r'(?<=\|)[^|]*',s).group()

re.search(r'(?拆分和检查长度可能仍然比正则表达式快:

for line in f:
    spl = line.split("|",2)
    if len(spl) > 2:
        print(spl[1])
       ....
匹配行和非匹配行上的某些计时:

In [24]: s = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"

In [25]: %%timeit                                                        
    spl = s.split("|",2)
    if len(spl) > 2:
        pass
   ....: 
1000000 loops, best of 3: 413 ns per loop

In [26]: r = re.compile(r'(?<=\|)[^|]*')

In [27]: timeit r.search(s)                                            
1000000 loops, best of 3: 452 ns per loop

In [28]: s = "78 Indonesia Pamela Reid preid25@gravatar.com 147.3.67.193"

In [29]: timeit r.search(s)
1000000 loops, best of 3: 1.66 µs per loop

In [30]: %%timeit                       
    spl = s.split("|",2)
    if len(spl) > 2:
        pass
   ....: 
1000000 loops, best of 3: 342 ns per loop
由于每条管线中的管道数量始终相同:

def main(argv):
    seen = set() # only use if you actually need  a set of all names
    with open("test.txt", 'r') as infile:
        r = csv.reader(infile, delimiter="|")
        for row in r:
            v = row[1]
            if v:
                filename = "bby_" + v + ".dat"
                existingFile = open(filename, 'a')
                existingFile.write(row)
                existingFile.close()
                seen.add(v)
            else:
                print "Empty"
如果在附加到文件时/else看起来是多余的,那么如果出于其他原因想保留一组行[1],每次都可以添加到该集合中,除非您确实想要一组我将从代码中删除的所有名称

将相同的逻辑应用于拆分:

def main(argv):
    seen = set()
    with open("test.txt", 'r') as infile:
        _spl = str.split
        for row in infile:
            v = _spl(row,"|",2)[1]
            if v:
                filename = "bby_" + v + ".dat"
                existingFile = open(filename, 'a')
                existingFile.write(row)
                existingFile.close()
                seen.add(v)
            else:
                print "Empty"
会导致大量开销的是不断地打开和写入,但除非您能够将所有行存储在内存中,否则没有简单的方法可以绕过它

就阅读而言,在一个1000万行的文件上,仅仅拆分两倍的内容就比csv阅读器要好:

In [15]: with open("in.txt") as f:
   ....:     print(sum(1 for _ in f))
   ....: 
10000000

In [16]: paste
def main(argv):
    with open(argv, 'r') as infile:
        for row in infile:
            v = row.split("|", 2)[1]
            if v:
                pass
## -- End pasted text --

In [17]: paste
def main_r(argv):
    with open(argv, 'r') as infile:
        r = csv.reader(infile, delimiter="|")
        for row in r:
            if row[1]:
                pass

## -- End pasted text --

In [18]: timeit main("in.txt")
1 loops, best of 3: 3.85 s per loop

In [19]: timeit main_r("in.txt")
1 loops, best of 3: 6.62 s per loop

如果始终存在相同数量的管道,则可以使用正则表达式:

[^|]+(?=(?:\|[^|]+\|?){4}$)

以下是Python 3.4.3上有意义答案的性能:

In [4]: timeit.timeit('s.split("|", 2)[1]', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"')
Out[4]: 0.43930888699833304

In [10]: timeit.timeit('re.search(r"^[^a-zA-Z]*([a-zA-Z]+)", s).group(1)', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"; import re')
Out[10]: 1.234878903022036

In [16]: timeit.timeit('re.search("^\d*\|(\w+?)?\|", s).group(1)', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"; import re')
Out[16]: 1.8305770770530216
如果没有管道:

In [24]: timeit.timeit('s.split("|", 2)[1] if "|" in s else None', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"')
Out[24]: 0.494665392965544

In [25]: timeit.timeit('s.split("|", 2)[1] if "|" in s else None', 's =  ""')
Out[25]: 0.04492994397878647


你可以一行一行地解析它,然后根据知识无所谓如果有一个管道,是否总是会有多个管道,或者管道会出现在任何地方?@padraiccningham我不明白你在说什么,我的意思是,有管道字符的行看起来总是像你的输入示例一样,regex非常灵活,但这种灵活性来了要付出代价。正如Yaroslav Admin的回答所示,使用正则表达式执行此任务比使用
str.split
方法慢得多。OP说子句可能是空的,所以您可能希望
d*
对于第一部分您是绝对正确的。我假设OP只指第二个子句可能是空的。修复了。这还考虑了第一个元素。打印第一组。如果没有管道怎么办?@AvinashRaj:那么数据文件被破坏了,因此如果程序引发异常是可以接受的。根据OP,他们只需要从第二列提取数据,因此可以合理地假设总是会有(至少)两列。@AvinashRaj请参阅添加的部分。输入中始终有管道。只有数据可以为空。@ViChU:Yaroslav的代码在管道存在的情况下可以正常工作,但第二列为空:它只返回一个空字符串。@ViChU,管道的数量始终相同吗?这将是最佳方法中的一个重要因素是肯定的。。相同数量的管道。然后只需检查
就可以拆分。如果v
将是最快的方法,您知道第二列中可能出现的国家/地区吗?如果是这样,我们可能可以将io速度提高很多bit@ViChU,没有人能在第一时间就把它做好;)保留列表或
行的目的是什么[1]的
?唯一的问题是将
与一起使用,这是python2.4上应该使用的所有其他工具条
In [4]: timeit.timeit('s.split("|", 2)[1]', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"')
Out[4]: 0.43930888699833304

In [10]: timeit.timeit('re.search(r"^[^a-zA-Z]*([a-zA-Z]+)", s).group(1)', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"; import re')
Out[10]: 1.234878903022036

In [16]: timeit.timeit('re.search("^\d*\|(\w+?)?\|", s).group(1)', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"; import re')
Out[16]: 1.8305770770530216
In [24]: timeit.timeit('s.split("|", 2)[1] if "|" in s else None', 's = "78|Indonesia|Pamela|Reid|preid25@gravatar.com|147.3.67.193"')
Out[24]: 0.494665392965544

In [25]: timeit.timeit('s.split("|", 2)[1] if "|" in s else None', 's =  ""')
Out[25]: 0.04492994397878647