Python 将os.system()与sed命令一起使用时出现问题
我正在写一个小方法来替换文件中的一些文本。 我需要的唯一参数是新文本,因为它始终是要替换的相同文件和文本 当我尝试使用该方法的参数时,在使用os.system()调用时遇到问题 如果我使用下面这样的字符串,则一切正常:Python 将os.system()与sed命令一起使用时出现问题,python,Python,我正在写一个小方法来替换文件中的一些文本。 我需要的唯一参数是新文本,因为它始终是要替换的相同文件和文本 当我尝试使用该方法的参数时,在使用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) 现在
stringId = "GRRRRRRRRR"
cmd="sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' path/file.old > path/file.new"
os.system(cmd)
现在,如果我尝试给出一个字符串作为参数,如下面所示,则不会执行该命令。
我做了一个打印,看看命令是否正确,它是正确的。如果我复制/粘贴到shell,我甚至可以成功地执行它
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)
有人知道怎么回事吗
谢谢要帮助您调试它,请尝试添加:
print repr(cmd)
可能是在复制和粘贴时,普通打印隐藏的命令中包含了一些特殊字符。可能是缩进问题 以下各项工作正常:
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
)作为变量。错误在于存在一些差异。是的,我知道这没有帮助,但你需要找出区别
尝试运行以下命令:
import os
def updateExportConfigId(id):
stringId = "%s" % id
cmd1 = "sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' path/file.old > path/file.new"
stringId = "GRRRRRRRRR"
cmd2 = "sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=" + stringId + "/g' path/file.old > path/file.new"
print "cmd1:" , cmd1
print "cmd2:" , cmd2
print cmd1 == cmd2
updateExportConfigId("GRRRRRRRRR")
代码应打印:
sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=GRRRRRRRRR/g' path/file.old > path/file.new
sed '1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=GRRRRRRRRR/g' path/file.old > path/file.new
True
从而表明它们完全相同。如果最后一行是“False”,那么它们就不一样了,您应该能够看到差异。也许只使用它会有所帮助。因此,从前面的回答中,我们现在知道,
id
是一个Unicode字符串,这使得cmd1成为Unicode字符串,os.system()正在将其转换为字节字符串,以便在默认编码中执行
a) 我建议使用子流程而不是os.system()
b) 我建议不要将内置函数的名称用作变量(id
)
c) 我建议在执行之前将字符串显式编码为字节字符串:
if isinstance(cmd,unicode):
cmd = cmd.encode("UTF-8")
d) 对于Lennart Regebro的建议,添加:
assert type(cmd1) == type(cmd2)
之后
最后,我找到了一种运行os.system(cmd)的方法 “清除”cmd字符串的简单技巧:
os.system(str(cmd))
现在,我可以用我需要的所有参数构建cmd,最后我只需使用str()调用“清理”它,然后再使用os.system()调用运行它
非常感谢你的回答
swon强制性:不要使用操作系统。
系统
-使用模块:
使用此代码,您可以传递管理器id,它可以包含空格、引号字符等。文件名也可以传递给函数,还可以包含空格和其他一些特殊字符。这是因为您的shell没有被不必要地调用,所以在您的操作系统上只启动一个进程,并且您不必担心转义特殊的shell字符
另一种选择:不要启动sed。使用python的模块
这样称呼它:
updateExportConfigID('GRRRR', open('path/file.old'), open('path/file.new', 'w'))
不需要新的流程。我已经尝试过了,结果是一样的。使用print repr(cmd),我可以看到这两种情况之间存在差异:cmd='mv test.dat test.+stringId打印repr(cmd)的输出是:u'mv test.dat test.new',其中我使用了“new”字符串作为参数,但如果cmd=“sed”1,$s/MANAGER_ID=[0-9]*/MANAGER_ID=“+stringId+”/g'test.dat>test.new打印repr(cmd)的输出是:u“sed'1,$s/MANAGER\u ID=[0-9]*/MANAGER\u ID=adsf/g'test.dat>test.new”我尝试了所有字符串组合,使用了“”,“%s”,“+”+”“,…在解释这两种情况之间的差异时,尝试实际使用相同的示例。我能看到这两种情况之间的唯一区别是使用完全不同的命令。这没什么帮助。为了正确起见,
id
不是保留字。它是一个内置函数。不使用它们的意义仍然适用。只是一个简短的提示。stringId=“%s”%id行完全无用。%s“%id”与str(id)完全相同,如果id是字符串(在您的示例中应该是字符串),那么它本身当然是无用的。您正在运行哪一版本的Python?除了遵循更改id变量名和删除stringID行(以及在我的系统上设置合法值的路径)的建议之外,我让您的代码在Python 2.4.3上运行良好,即使没有str(cmd)。还有一件事,按照设置的方式,您将更改MANAGER\u ID=some\u ID的所有出现次数。如果您的文件中只有一个MANAGER\u ID,可能这就是您想要的,但是如果您的文件中有多个MANAGER\u ID,您将把它们都设置为相同的值。嗯,我真的很生气。。我测试过,字符串是一样的。区别仅出现在print repr()print repr(command1):u“sed”1,$s/MANAGER\u ID=[0-9]*/MANAGER\u ID=GRRRR/g”file.old>file.new“print repr(cmd2):“sed”1,$s/MANAGER\u ID=[0-9]*/MANAGER\u ID=GRRRR/g”file.old>file.new“在这种情况下,cmd2使用硬编码字符串,我可以通过os.system()调用运行cmd2。ThanksAha,所以区别在于第一种情况是unicode,另一种情况是字符串。出于某种原因,用unicode调用os.system()是行不通的。这一定意味着传入方法的变量id是unicode。
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'))
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'))