【问题标题】:Replace string in a specific line using python使用python替换特定行中的字符串
【发布时间】:2010-01-04 08:36:46
【问题描述】:

我正在编写一个 python 脚本来替换具有特定扩展名 (.seq) 的目录中每个文本文件中的字符串。替换的字符串应该只来自每个文件的第二行,并且输出是一个新的子目录(称为 clean),其文件名与原始文件相同,但带有 *.clean 后缀。输出文件包含与原始文件完全相同的文本,但替换了字符串。我需要用 'N' 替换所有这些字符串:'K','Y','W','M','R','S'。

这是我在谷歌搜索后想出的。它非常混乱(编程的第二周),它停止将文件复制到干净的目录中而不替换任何东西。非常感谢任何帮助。

之前谢谢!

import os, shutil

os.mkdir('clean')

for file in os.listdir(os.getcwd()):
    if file.find('.seq') != -1:
        shutil.copy(file, 'clean')

os.chdir('clean')

for subdir, dirs, files in os.walk(os.getcwd()):
    for file in files:
        f = open(file, 'r')
        for line in f.read():
            if line.__contains__('>'): #indicator for the first line. the first line always starts with '>'. It's a FASTA file, if you've worked with dna/protein before.
                pass
            else:
                line.replace('M', 'N')
                line.replace('K', 'N')
                line.replace('Y', 'N')
                line.replace('W', 'N')
                line.replace('R', 'N')
                line.replace('S', 'N')

【问题讨论】:

    标签: python replace


    【解决方案1】:

    一些注意事项:

    1. string.replacere.sub 不在原地,因此您应该将返回值分配回您的变量。
    2. glob.glob 更适合在与定义的模式匹配的目录中查找文件...
    3. 也许您应该在创建目录之前检查该目录是否已经存在(我只是假设,这可能不是您想要的行为)
    4. with 语句负责以安全的方式关闭文件。如果你不想使用它,你必须使用tryfinally
    5. 在您的示例中,您忘记将后缀 *.clean ;)
    6. 你没有真正写文件,你可以像我在我的例子中那样做,或者使用fileinput模块(直到今天我才知道)

    这是我的例子:

    import re
    import os
    import glob
    
    source_dir=os.getcwd()
    target_dir="clean"
    source_files = [fname for fname in glob.glob(os.path.join(source_dir,"*.seq"))]
    
    # check if target directory exists... if not, create it.
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)
    
    for source_file in source_files:
       target_file = os.path.join(target_dir,os.path.basename(source_file)+".clean")
       with open(source_file,'r') as sfile:
          with open(target_file,'w') as tfile:
             lines = sfile.readlines()
             # do the replacement in the second line.
             # (remember that arrays are zero indexed)
             lines[1]=re.sub("K|Y|W|M|R|S",'N',lines[1])
             tfile.writelines(lines)
    
    print "DONE"
    

    希望对你有帮助。

    【讨论】:

      【解决方案2】:

      您应该将line.replace('M', 'N') 替换为line=line.replace('M', 'N')。 replace 返回原始字符串的副本,并替换了相关的子字符串。

      更好的方法 (IMO) 是使用 re.

      import re
      
      line="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      line=re.sub("K|Y|W|M|R|S",'N',line)
      print line 
      

      【讨论】:

      • 你也可以先编译re。
      【解决方案3】:

      以下是一些一般性提示:

      1. 不要使用find 来检查文件扩展名(例如,这也会匹配“file1.seqdata.xls”)。至少使用file.endswith('seq'),或者更好的是os.path.splitext(file)[1]

      2. 实际上,不要完全这样做。这就是你想要的:

        import glob
        seq_files = glob.glob("*.seq")
        
      3. 不要复制文件,只使用一个循环会容易得多:

        for filename in seq_files:
            in_file = open(filename)
            out_file = open(os.path.join("clean", filename), "w")
            # now read lines from in_file and write lines to out_file
        
      4. 不要使用line.__contains__('>')。你的意思是

        if '>' in line:
        

        (将在内部调用__contains__)。但实际上,您想知道行以“>”开头,而不是行内是否有一个,无论是否在开头。所以更好的方法是:

        if line.startswith(">"):
        

        我不熟悉您的文件类型;如果">" 检查真的只是为了确定第一行,那么有更好的方法来做到这一点。

      5. 您不需要if 块(您只需pass)。写起来更干净

        if not something:
            do_things()
        other_stuff()
        

        而不是

        if something:
            pass
        else:
            do_things()
        other_stuff()
        

      祝学习 Python 愉快!

      【讨论】:

        【解决方案4】:

        您需要将替换结果分配回“行”变量

        line=line.replace('M', 'N')
        

        您也可以使用模块文件输入进行就地编辑

        import os, shutil,fileinput
        if not os.path.exists('clean'):
            os.mkdir('clean')
        
        for file in os.listdir("."):
            if file.endswith(".seq"):
                shutil.copy(file, 'clean')
        
        os.chdir('clean')
        
        for subdir, dirs, files in os.walk("."):
            for file in files:
                f = fileinput.FileInput(file,inplace=0)
                for n,line in enumerate(f):
                    if line.lstrip().startswith('>'):
                        pass
                    elif n==1: #replace 2nd line
                        for repl in ["M","K","Y","W","R","S"]:
                            line=line.replace(ch, 'N')
                    print line.rstrip()
                f.close()
        

        将 inplace=0 更改为 inplace=1 以就地编辑您的文件。

        【讨论】:

          【解决方案5】:

          line.replace 不是一个mutator,它保持原始字符串不变并返回一个带有替换的新字符串。您需要将代码更改为line = line.replace('R', 'N') 等。

          我认为您还想在 else 子句的末尾添加 break 语句,这样您就不会遍历整个文件,而是在处理完第 2 行后停止。

          最后,您需要实际写出包含更改的文件。到目前为止,您只是在读取文件并更新程序变量“line”中的行。您还需要实际创建一个输出文件,您将在其中写入修改后的行。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-04-28
            • 2017-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-14
            • 2018-03-04
            相关资源
            最近更新 更多