在Python中通过subprocess.call使用Sed进行文件替换

1 投票
2 回答
1707 浏览
提问于 2025-04-18 04:06

我有一个文件中的一列数据,想用另一个文件中的一列数据来替换它。我想在Python中用sed来实现这个功能,但我不太确定自己是不是做对了。也许代码能让事情更清楚一些:

 20 for line in infile1.readlines()[1:]:
 21         element = re.split("\t", line)
 22         IID.append(element[1])
 23         FID.append(element[0])
 24 
 25 os.chdir(binary_dir)
 26 
 27 for files in os.walk(binary_dir):
 28         for file in files:
 29                 for name in file:
 30                         if name.endswith(".fam"):
 31                                 infile2 = open(name, 'r+')
 32 
 33 for line in infile2.readlines():
 34         parts = re.split(" ", line)
 35         Part1.append(parts[0])
 36         Part2.append(parts[1])
 37 
 38 for i in range(len(Part2)):
 39         if Part2[i] in IID:
 40                 regex = '"s/\.*' + Part2[i] + '/' + Part1[i] + ' ' + Part2[i] + '/"' + ' ' + phenotype 
 41                 print regex
 42                 subprocess.call(["sed", "-i.orig", regex], shell=True)

这就是print regex的作用。系统在执行sed的过程中似乎卡住了,因为它在那儿停留了很长时间,没有任何反应。

"s/\.*131006/201335658-01 131006/" /Users/user1/Desktop/phenotypes2

谢谢你的帮助,如果你需要进一步的解释,请告诉我!

2 个回答

1

第一个问题是你在使用列表参数时加了 shell=True。你要么去掉 shell=True,要么用字符串参数(也就是完整的命令)来替代:

from subprocess import check_call

check_call(["sed", "-i.orig", regex])

否则,参数('-i.orig'regex)会被传给 /bin/sh,而不是 sed

第二个问题是你没有提供输入文件,所以 sed 期待从标准输入(stdin)获取数据,这就是它看起来像是卡住的原因。

如果你想直接在文件中进行修改,可以使用 fileinput 模块

#!/usr/bin/env python
import fileinput

files = ['/Users/user1/Desktop/phenotypes2'] # if it is None it behaves like sed
for line in fileinput.input(files, backup='.orig', inplace=True):
    print re.sub(r'\.*131006', '201335658-01 13100', line),

fileinput.input() 会把输出重定向到当前文件,也就是说,print 会改变这个文件。

逗号的作用是设置 sys.stdout.softspace,以避免出现重复的换行。

1

如果你有Python和re模块,就不需要用sed了。这里有个例子,教你怎么用re来替换字符串中的某个模式。

>>> import re
>>> line = "abc def ghi"
>>> new_line = re.sub("abc", "123", line)
>>> new_line
'123 def ghi'
>>> 

当然,这只是用Python实现这个功能的一种方法。我觉得你也可以用str.replace()来完成这个任务。

撰写回答