读取由\ n分隔的python中的文件,但忽略最后\ n

时间:2017-10-11 14:42:21

标签: python bash for-loop newline

我有一个名为list.txt的文件,如下所示:

input1
input2
input3

我确定最后一行(input3)后面没有空行。然后我有一个python脚本,它将逐行读取该文件,并将文本写入更多文本以创建3个文件(每行一个):

import os
os.chdir("/Users/user/Desktop/Folder")

with open('list.txt','r') as f:
    lines = f.read().split('\n')

    #for l in lines:
        header = "#!/bin/bash \n#BSUB -J %s.sh \n#BSUB -o /scratch/DBC/user/%s.sh.out \n#BSUB -e /scratch/DBC/user/%s.sh.err \n#BSUB -n 1 \n#BSUB -q normal \n#BSUB -P DBCDOBZAK \n#BSUB -W 168:00\n"%(l,l,l)
        script = "cd /scratch/DBC/user\n"
        script2 = 'grep "input" %s > result.%s.txt\n'%(l,l)
        all= "\n".join([header,script,script2])

        with open('script_{}.sh'.format(l), 'w') as output:
            output.write(all)

我的问题是,这会创建4个文件,而不是3个:script_input1.sh,script_input.sh,script_input3.sh和script_.sh。最后一个文件没有文本,其他文件的input1或input2或input3。

似乎Python逐行读取我的list.txt,但当它到达“input3”时,它会以某种方式继续?如何告诉Python逐行读取我的文件,用“\ n”分隔,但在最后一个文本后停止?

5 个答案:

答案 0 :(得分:3)

首先,不要将整个文件读入内存 - 文件是可迭代的,因此逐行读取文件的正确方法是:

with open("/path/to/file.ext") as f:
    for line in f:
        do_something_with(line)

现在在你的for循环中,你只需要删除该行,如果它是空的,则忽略它:

with open("/path/to/file.ext") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        do_something_with(line)

稍微不相关但Python有多行字符串,因此您不需要连接:

# not sure I got it right actually ;)
script_tpl = """
#!/bin/bash 
#BSUB -J {line}.sh 
#BSUB -o /scratch/DBC/user/{line}.sh.out 
#BSUB -e /scratch/DBC/user/{line}.sh.err 
#BSUB -n 1 
#BSUB -q normal 
#BSUB -P DBCDOBZAK 
#BSUB -W 168:00
cd /scratch/DBC/user
grep "input" {line} > result.{line}.txt
"""

with open("/path/to/file.ext") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        script = script_tpl.format(line=line)
        with open('script_{}.sh'.format(line), 'w') as output:
            output.write(script)

作为最后一点:避免在脚本中更改目录,而是使用os.path.join()代替绝对路径。

答案 1 :(得分:1)

使用您当前的方法,您需要:

  • 检查lines中的最后一个元素是否为空(lines[-1] == ''
  • 如果是,请丢弃它(lines = lines[:-1])。
with open('list.txt','r') as f:
    lines = f.read().split('\n')

if lines[-1] == '':
    lines = lines[:-1]

for line in lines:    
    print(line)

不要忘记,文件不以换行符结尾(末尾有一个空行)是合法的......这将处理这种情况。

或者,正如@setsquare指出的那样,您可能想尝试使用readlines()

with open('list.txt', 'r') as f:
    lines = [ line.rstrip('\n') for line in f.readlines() ]

for line in lines:
    print(line)

答案 2 :(得分:1)

您是否考虑过使用readlines()而不是read()?这将让Python为您解决最后一行是否具有\ n的问题。

请记住,如果输入文件在最后一行上有\ n,那么使用read()并按'\ n'分割将创建一个额外的值。例如:

my_string = 'one\ntwo\nthree\n'
my_list = my_string.split('\n')
print my_list
# >> ['one', 'two', 'three', '']

潜在的解决方案

lines = f.readlines()
# remove newlines
lines = [line.strip() for line in lines]
# remove any empty values, just in case
lines = filter(bool, lines)

举一个简单的例子,请看这里:How do I read a file line-by-line into a list?

答案 3 :(得分:1)

f.read()返回一个以换行符结尾的字符串,split尽职尽责地将最后一行与空字符串分开。目前尚不清楚为什么要将整个文件明确地读入内存;只是迭代文件对象,让它处理行拆分。

with open('list.txt','r') as f:
    for l in f:
        # ...

答案 4 :(得分:0)

我认为你使用错误分裂。

如果您有以下内容:

text = 'xxx yyy'
text.split(' ') # or simply text.split()

结果将是

['xxx', 'yyy']

现在,如果你有:

text = 'xxx yyy ' # extra space at the end
text.split()

结果将是

['xxx', 'yyy', '']

,因为分裂得到了每个&之前和之后的内容。 ' (空间)。在这种情况下,在最后一个空格之后有空字符串。

您可能会使用的一些功能:

strip([chars]) # This removes all chars at the beggining or end of a string

示例:

text = '___text_about_something___'
text.strip('_')

结果将是:

'text_about_something'

在您的特定问题中,您可以简单地说:

lines = f.readlines() # read all lines of the file without '\n'
for l in lines:
    l.strip(' ') # remove extra spaces at the start or end of line if you need