Python 创建符合标准的文件

Python 创建符合标准的文件,python,sed,awk,grep,Python,Sed,Awk,Grep,我有一个逗号分隔的文件。线条看起来像这样 1,2,3,4,5 6,7,8 9,10 11,12,13,14,15 我需要在所有行中有5列。所以新文件将是 1,2,3,4,5 6,7,8,, 9,10,,, 11,12,13,14,15 换句话说,如果一行中少于4个逗号。在末尾添加所需的数字。有人告诉我,有一个python模块也会做同样的事情。我在哪里可以找到这样的模块?awk是否更适合此类任务?您正在寻找的模块是。您仍然需要确保列表满足最小长度要求: with open('output.cs

我有一个逗号分隔的文件。线条看起来像这样

1,2,3,4,5
6,7,8
9,10
11,12,13,14,15
我需要在所有行中有5列。所以新文件将是

1,2,3,4,5
6,7,8,,
9,10,,,
11,12,13,14,15

换句话说,如果一行中少于4个逗号。在末尾添加所需的数字。有人告诉我,有一个python模块也会做同样的事情。我在哪里可以找到这样的模块?awk是否更适合此类任务?

您正在寻找的模块是。您仍然需要确保列表满足最小长度要求:

with open('output.csv', 'wb') as output:
    input = csv.reader(open('faultyfile.csv', 'rb'))
    output = csv.writer(output, dialect=input.dialect)
    for line in input:
        if len(line) < 5:
            line.extend([''] * (5 - len(line)))
        output.writerow(line)
以open('output.csv','wb')作为输出的
:
输入=csv.reader(打开('faultyfile.csv','rb'))
输出=csv.writer(输出,方言=输入,方言)
对于行输入:
如果长度(线)<5:
行。扩展(['']*(5-列(行)))
output.writerow(第行)
如注释中所述,当您确实不需要时,它会将整个文件读入内存。要做到这一点,并非一蹴而就:

import shutil
def correct_file(fname):
    with open(fname,'r') as fin, open('temp','w') as fout:
        for line in fin:
           new = line[:-1]+(4-line.count(','))*',' + '\n'
           fout.write(new)
    shutil.move('temp',fname)
这将使任何名为
temp
的文件在当前目录中消失。当然,您可以始终使用
tempfile
模块来解决这个问题


对于更详细但防弹的(?)版本:

import shutil
import tempfile
import atexit
import os

def try_delete(fname):
    try:
       os.unlink(fname)
    except OSError:
       if os.path.exists(fname):
          print "Couldn't delete existing file",fname

def correct_file(fname):
    with open(fname,'r') as fin, tempfile.NamedTemporaryFile('w',delete=False) as fout:
        atexit.register(lambda f=fout.name: try_delete(f)) #Need a closure here ...
        for line in fin:
           new = line[:-1]+(4-line.count(','))*',' + '\n'
           fout.write(new)
    shutil.move(fout.name,fname) #This should get rid of the temporary file ...
如果您确定它将始终为n个项目长(在本例中为5),并且在打开文件之前您将始终知道。。。这样做内存效率更高


如果您不介意使用awk,那么它很简单:

$ cat data.txt 
1,2,3,4,5
6,7,8
9,10
11,12,13,14,15

$ awk -F, 'BEGIN {OFS=","} {print $1,$2,$3,$4,$5}' data.txt 
1,2,3,4,5
6,7,8,,
9,10,,,
11,12,13,14,15
这可能适用于您(GNU-sed):


如果您没有得到答案,请不要再提问模块是
csv
,尽管您可能需要手动填充您阅读的列表。@Minion91--这是不同的。以前OP只是想跳过格式错误的文件。这是关于更正它们的问题。这是为了一些代码挑战,不是吗?为什么要在再次写之前将所有内容读入内存?您可以轻松地逐行执行此操作。:-)@MartijnPieters——如果要避免使用
shutil.move
来移动临时文件,则不需要。我想您可以使用
tempfile
+
shutil
安全地创建一个临时文件,然后将其移动,但是如果该文件足够小,可以放入内存,为什么不将其全部放在适当的位置?这会有什么问题呢?这些文件有多大?@MartijnPieters——没问题。它只是更复杂而已。@MartijnPieters——在内存中完成这一切的另一个好处是,如果读取过程中途中断,磁盘上就不会剩下一个处理了一半的文件。我想你可能会说,如果这个过程在写的中途中断,你就丢失了数据……为什么要在再次写之前把所有的东西都读入内存呢?您可以轻松地逐行执行此操作。:-)只是因为他说总是五点。。。这考虑到某些文件中可能有6或7个…您也提出了一个很好的观点。。。假设它总是5,并且在查看文件之前您总是知道这一点:)
list(line.split(','))
是多余的。还有,为什么不使用listcomp呢
rows=[line.split(',')表示f中的行]
?我的最后一条评论,
print“\n.join([str(r)…])
——您可以省略方括号,只使用生成器。如果数据是以管道分隔的,而不是,如何定义它?从链接上找到的。非常感谢!如果在读取时使用分隔符=“^”,则在写入时它不使用相同的分隔符(扩展)?好的,在python中,如果您尝试一下,一切都会正常工作。明白了。输出csv.writer也需要被告知要使用什么分隔符。我已经稍微更新了代码,将输出csv.writer配置为与输入阅读器相同的方言。awk从未停止过,这让我感到惊讶。
with open('somefile.txt') as f:
      rows = []
      for line in f:
          rows.append(line.split(","))

max_cols = len(max(rows,key=len))
for row in rows:
    row.extend(['']*(max_cols-len(row))

print "\n".join(str(r) for r in rows)
 with open("f1","r"):
      with open("f2","w"):
          for line in f1:
              f2.write(line+(","*(4-line.count(",")))+"\n")
$ cat data.txt 
1,2,3,4,5
6,7,8
9,10
11,12,13,14,15

$ awk -F, 'BEGIN {OFS=","} {print $1,$2,$3,$4,$5}' data.txt 
1,2,3,4,5
6,7,8,,
9,10,,,
11,12,13,14,15
 sed ':a;s/,/&/4;t;s/$/,/;ta' file