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