Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.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,对Python来说是全新的。我正在使用csv阅读器解析一些文件。我将解析使用3个不同分隔符的信息。逗号、管道和空格(目前) 我有这个: 打开(文件路径,“r”)作为fp的: file_lines=fp.readlines() 分隔符=重新搜索(“\w+([^\w])”,文件行[0])。组(1) reader=csv.reader(文件行,分隔符=分隔符) 打印('分隔符:[{}]'。格式(分隔符)) 行列表=[读卡器中的行对行] 打印(行列表) 这适用于我的comma.txt文件。但是当传入我

对Python来说是全新的。我正在使用
csv
阅读器解析一些文件。我将解析使用3个不同分隔符的信息。逗号、管道和空格(目前)

我有这个:

打开(文件路径,“r”)作为fp的
:
file_lines=fp.readlines()
分隔符=重新搜索(“\w+([^\w])”,文件行[0])。组(1)
reader=csv.reader(文件行,分隔符=分隔符)
打印('分隔符:[{}]'。格式(分隔符))
行列表=[读卡器中的行对行]
打印(行列表)
这适用于我的
comma.txt
文件。但是当传入我的
pipe.txt
文件时,它会先捕获空白,然后再捕获实际的管道

带有管道的行的示例输入如下所示:

管道:
Bouillon | Francis | G | M | Blue | 6-3-1975

空白:
Bouillon Francis G M Blue 6-3-1975

逗号:
Bouillon,Francis,G,M,Blue,6-3-1975


你们能推荐另一种方法吗?或者我应该改一下我的正则表达式吗?

从我的头脑中,我会选择这样的东西

([^\w-]|[|]|[,])
如果你修剪它,你会得到你的分隔符。查看以测试您的文件。它是JavaSript正则表达式,但我发现它对于调试Python正则表达式也很有用

编辑

正如@h4z3正确指出的,您可以简化:

([^\w-]|[|,])

2方法:

(您也可以不使用
csv.reader
继续,只需按
sep
进行拆分,并带有尾随空格)

示例文件:

pipe.txt:


逗号.txt:


space.txt


输出(对于文件
comma.txt
pipe.txt
):


由于
skipinitialspace=True
功能,因此
space.txt的输出更加清晰:

['Bouillon', 'Francis', 'G', 'M', 'Blue', '6-3-1975']
['a', 'b', 'c', 'd', 'f', 'g']

或不带
csv.reader

with open('comma.txt') as f:
    line = next(f).strip()
    sep = re.search(r'^\w+([\s\|,]+)', line).group(1)
    pat = re.compile(sep)

    for row in chain(iter([line]), f):
        print(pat.split(row.strip()))
输出:

['Bouillon', 'Francis', 'G', 'M', 'Blue', '6-3-1975']
['a', 'b', 'c', 'd', 'f', 'g']

享受吧

正如我在评论中所说,正则表达式按预期工作。(

Bouillon | Francis | G | M | Blue | 6-3-1975
\w+([^\w])
获得
'Bouillon'
作为
组(0)
(完全匹配),因为空格是第一个非单词字符

如果要在数据中保留填充空格,或者数据可能包含空格(例如,
Name-Surname | Age
),则不能在搜索管道和逗号的同一正则表达式中搜索空格,因为第一个值中的填充空格或空格将被捕获

(除非您在该正则表达式中搜索多个字符,但您需要更复杂的代码,而且我喜欢简单易懂的代码。)

您可以做的是:

  • 搜索管道和逗号(假设管道分隔的内容没有逗号,逗号分隔的内容没有管道)。仅当搜索失败时才假定为空白
  • 另一种方法是分层

    • 假设管道分隔文件的内容中可以包含任何内容(包括逗号(与第一种方法相反)和空格)
    • 假设以逗号分隔的文件中可以包含除管道以外的任何内容
    • 假设以空格分隔的文件没有用作分隔符的字符
    然后检查需要分层:首先检查是否存在管道。如果没有,请检查逗号。如果没有,请检查。。。如果没有,则假定为空格

    这可以实现为一个简单的for循环,您可能的delimeters可以是一个简单的字符串,从最重要的分隔符-
    “|,”
    。正则表达式对于这样简单的事情是不好的

  • 您可以尝试使用该类来确定要解析的csv的方言

    函数的
    sniff()
    接受一个可能的分隔符字符串,它将使用该字符串尝试并确定如何解析文件。这很聪明,但是潜在的分隔符包含一个空格,而
    |
    文件有空格这一事实对它来说是个问题。如果您用空格传递
    分隔符=',|
    ,它会将该空格标识为用
    分隔的文件的分隔符。一个选项是尝试使用非空格分隔符,如果失败,则尝试使用空格:

    import csv
    with open('test_space.csv') as csvfile:
        try:
            dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=',|')
        except:
            csvfile.seek(0)
            dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=' ')
        dialect.skipinitialspace = True
        csvfile.seek(0)
    
       reader = csv.reader(csvfile, dialect)
        for line in reader:
            print(list(map(str.strip, line)))
    
    这将正确地将这样的行标识为以空格分隔的行:

    Bou|illon Francis G M Bl,ue 6-3-1975
    Bouillon Francis G M Blue 6-3-1975
    Bouillon Franc,is G M Blue 6-3-1975
    
    这将很难用正则表达式方法处理

    但如果你在每一行都有潜在的delimeters,它会匹配这些。例如,它将其解析为逗号分隔(我假设它在每行中看到一个逗号):


    在您的示例中,第一个非单词字符是一个空格,因此它可以正常工作。;)只需在那一行上手动搜索你的正则表达式,你就会看到。因此,
    delimiter
    变量将是一个字符。我只是将其传递到
    csv.reader
    。目标是,如果打开一个
    comma.txt
    文件并找到一个逗号,它将捕获该逗号并将其作为分隔符传递。与
    pipe.txt
    文件相同,并带有空格。假设您的输入内容中没有任何管道(但可能有逗号),并且用逗号分隔的内容可能有空格,而带空格的内容没有任何以前的分隔符,则您可以自上而下检查层次结构。但是使用正则表达式,你可以找到第一个匹配的字符——这里的空格不是delimeter。@h4z3是的,这是正确的。我必须弄清楚,当它捕获像
    Johnny,
    Johnny |
    这样的群体时,如何让它工作。同样:
    Bouillon | Francis
    在内容和分隔符之间有空格。正如我所说,那么第一个捕获是一个空间,而不是一个管道。这是一个有效的示例还是
    Bouillon | Francis
    (没有空格)?因为正如我所说的,这个空间是被捕获的,方法会根据这个空间而改变?您知道,
    []
    已经可以作为一个信号工作了
    with open('space.txt') as f:
    ...
    
    ['Bouillon', 'Francis', 'G', 'M', 'Blue', '6-3-1975']
    ['a', 'b', 'c', 'd', 'f', 'g']
    
    with open('comma.txt') as f:
        line = next(f).strip()
        sep = re.search(r'^\w+([\s\|,]+)', line).group(1)
        pat = re.compile(sep)
    
        for row in chain(iter([line]), f):
            print(pat.split(row.strip()))
    
    ['Bouillon', 'Francis', 'G', 'M', 'Blue', '6-3-1975']
    ['a', 'b', 'c', 'd', 'f', 'g']
    
    search = re.search(r"[|,]", file_lines[0]) # add other delimeters in square brackets
    # we don't have capturing groups, our full catch (group 0) is first character that matches possible delimeters
    separator = search.group(0) if search else " " # is search was empty, assume space
    
    possible_separators = "|,"
    separator = " "
    for sep in possible_separators:
        if sep in file_lines[0]:
            separator = sep
            break
    
    import csv
    with open('test_space.csv') as csvfile:
        try:
            dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=',|')
        except:
            csvfile.seek(0)
            dialect = csv.Sniffer().sniff(csvfile.read(1024), delimiters=' ')
        dialect.skipinitialspace = True
        csvfile.seek(0)
    
       reader = csv.reader(csvfile, dialect)
        for line in reader:
            print(list(map(str.strip, line)))
    
    Bou|illon Francis G M Bl,ue 6-3-1975
    Bouillon Francis G M Blue 6-3-1975
    Bouillon Franc,is G M Blue 6-3-1975
    
    Bou|illon Francis G M Bl,ue 6-3-1975
    Bou,illon Francis G M Blue 6-3-1975
    Bouillon Franc,is G M Blue 6-3-1975