【问题标题】:Python: Find and replace strings in batch csv filesPython:在批处理 csv 文件中查找和替换字符串
【发布时间】:2015-05-01 20:27:01
【问题描述】:

我有数百个 csv 文件,我想搜索字符串“Keyed,Bet”并将其更改为“KeyedBet”。该字符串可能在文件中,也可能不在文件中,并且可能在不同文件的不同列中。

我拼凑了下面的脚本,但它不起作用。我肯定错误地使用了replace(),但不太清楚如何,并且在我真的不需要时创建一个新文件 - 如果它只是更新当前文件并以相同的名称保存,那将是很好(但超出了我的初学者能力)。

我哪里出错了?感谢您的帮助!

import os 
import csv


path='.'

filenames = os.listdir(path)

for filename in filenames:

    if filename.endswith('.csv'):
        r=csv.reader(open(filename))
        new_data = []
        for row in r:
            replace("Keyed,Bet","KeyedBet")
        new_data.append(row)   

    newfilename = "".join(filename.split(".csv")) + "_edited3.csv"
    with open(newfilename, "w") as f:
        writer = csv.writer(f)
        writer.writerows(new_data)

【问题讨论】:

  • “它不起作用。”为什么不?它做错了什么?有什么错误吗?
  • 老实说,这听起来像是 sed shell 命令(不是 python)的单行作业。
  • 为什么要重新发明轮子?只需下载sed + its dependencies,然后下载sed -i 's/Keyed,Bet/KeyedBet/ig' *.csv
  • @rojo 让您的评论成为答案。
  • @Andy 好吧,第一个问题是我对 replace() 的误解。我知道它需要有一个定义的字符串才能调用,但我没有这样做,但我不知道如何让它将 csv 中的行视为要搜索的字符串。

标签: python python-2.7 csv


【解决方案1】:

为什么要重新发明轮子?只需下载sed + its dependencies,然后

sed -i 's/Keyed,Bet/KeyedBet/ig' *.csv

编辑:上面的命令在 Linux 中应该可以正常工作。 Windows sed 要求其引用的标记是双引号,而不是单引号。

sed -i "s/Keyed,Bet,KeyedBet/ig" *.csv

【讨论】:

  • 嗯,这太棒了。
  • 好吧,当我通过 Cygwin 终端在测试文件上运行此命令时,它只是清空了文件。显然我做错了什么,但我使用了上面的确切命令。任何想法为什么会发生?
  • 啊,Windows sed 可能需要双引号而不是单引号。试试sed -i "s/Keyed,Bet/KeyedBet/ig" *.csv。抱歉,我早该想到的。
  • 是的,就是这样!工作得很漂亮,谢谢。最后一个问题:您为什么选择在命令中使用 /ig 而不是 /g?我查阅的大多数 sed 教程都试图更好地理解它,使用 /g- 有什么区别?再次感谢
  • /ig 不区分大小写。它还将用KeyedBet 替换keyed,beti 是不敏感的,g 是全局的(第一次替换后不会停止)。
【解决方案2】:

如果您想更改原始文件,您可以使用fileinput.inputinplace=True 来实际修改原始文件,glob 会在给定目录中为您找到所有 csv 文件:

from glob import iglob
import fileinput

path = '.' 

for line in fileinput.input(iglob(os.path.join(path, "*.csv")),inplace=True):
     print(line.replace("Keyed,Bet", "KeyedBet"),end="")

不完全是一行,但远少于 15 行。

创建新文件:

path='.'
from glob import iglob


for filename in  iglob(os.path.join(path,"*.csv")):
    with open(os.path.join(path,filename)) as f,open(os.path.join(path, os.path.splitext(filename)[0]+ "_edited3.csv"), "w") as f2:
        for line in f:
            f2.write(line.replace("Keyed,Bet", "KeyedBet"))

考虑到您正在替换字符串,只需打开没有 csv 模块的文件并使用str.replace 会更容易,如果您知道字符串总是出现在同一行中,那么 csv 模块将是一个更好的选择,但似乎子字符串可以出现在任何地方。

【讨论】:

  • 第一个选项的最后一行给了我“TypeError:replace() 没有关键字参数”。知道为什么会这样吗?
  • 感谢您的编辑。好吧,我从新版本中得到了一个语法错误,所以我查了一下,我猜 ,end="" 是 Python 3.x 的语法吗?所以,我从文档中尝试了 Python 2.7 语法(“Keyed,Bet”,“KeyedBet”),),这只是清空了整个文件——将它从 500M 文件缩小到 0kb。无法弄清楚为什么会发生这种情况,但是当我在 Cygwin 中尝试上述答案中的 sed 解决方案时,我得到了相同的结果。
  • 您需要添加from __future__ import print_function,这不会删除任何内容,因为如果您找到匹配项,它会替换或仅写入行
  • 上传您正在测试的文件的较小样本,我将在本地运行它
猜你喜欢
  • 1970-01-01
  • 2011-02-15
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-08
  • 2022-01-09
  • 1970-01-01
相关资源
最近更新 更多