使用os.system()时出现sed命令问题

2 投票
7 回答
11594 浏览
提问于 2025-04-15 12:36

我正在写一个小方法,用来替换文件中的一些文本。
我只需要一个参数,就是新的文本,因为要替换的文件和文本总是一样的。

我在使用 os.system() 这个调用时遇到了问题,当我尝试使用方法的参数时。

如果我使用下面这样的字符串,一切都能正常运行:

stringId = "GRRRRRRRRR"
cmd="sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' path/file.old > path/file.new"
os.system(cmd)

但是,如果我尝试像下面这样把字符串作为参数传入,命令就没有执行。
我打印出来检查命令是否正确,确实是正确的。如果我把它复制粘贴到我的命令行中执行,也能成功。

import os
def updateExportConfigId(id):
stringId = "%s" % id
cmd= "sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' path/file.old > path/file.new"
print "command is " + cmd
os.system(cmd)

有没有人知道哪里出了问题?

谢谢

7 个回答

2

可能是缩进的问题?

下面的代码可以正常运行:

import os

def updateExportConfigId(id):
    stringId = "%s" % id
    cmd= "sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' test.dat > test.new"
    print "command is " + cmd
    os.system(cmd)


updateExportConfigId("adsf")

另外,不要把保留字(比如 id)当作变量名使用。

2

为了帮助你调试,可以试着添加:

print repr(cmd)

可能是一些特殊字符在你复制粘贴命令时混进来了,而普通的打印功能没有显示出来。

5

首先要强调的是:不要使用 os.system,而是要用 subprocess 模块。

import subprocess

def updateExportConfigId(m_id, source='path/file.old', 
                             destination='path/file.new'):
    if isinstance(m_id, unicode):
        m_id = m_id.encode('utf-8')
    cmd= [
          "sed",
          ",$s/MANAGER_ID=[0-9]*/MANAGER_ID=%s/g" % m_id,  
          source,
         ]
    subprocess.call(cmd, stdout=open(destination, 'w'))

用这段代码,你可以传入管理者的ID,这个ID可以包含空格、引号等字符。文件名也可以传给这个函数,并且同样可以包含空格和其他一些特殊字符。这是因为你不需要额外启动一个命令行进程,所以在你的操作系统上启动的进程会少一个,你也不需要担心如何处理特殊的命令行字符。

还有一个选择:不要启动sed。可以使用Python的 re 模块。

import re
def updateExportConfigID(m_id, source, destination):
    if isinstance(m_id, unicode):
        m_id = m_id.encode('utf-8')
    for line in source:
        new_line = re.sub(r'MANAGER_ID=\d*', 
                          r'MANAGER_ID=' + re.escape(m_id), 
                          line)
        destination.write(new_line)

然后这样调用它:

updateExportConfigID('GRRRR', open('path/file.old'), open('path/file.new', 'w'))

不需要新的进程。

撰写回答