EEP*_*EEP 6 python regex escaping python-2.7
我目前正在尝试执行以下操作:
cmd = r'sudo sed -irn "1!N; s/<ip>127.0.0.1<\/ip>(\n.*4000.*)/<ip>0.0.0.0<\/ip>\1/" /usr/something.conf'
subprocess.Popen(cmd)
Run Code Online (Sandbox Code Playgroud)
然而,Popen抱怨说\\ 1是无效的引用.在pdb中检查它我看到了,
'sudo sed -irn "1!N; s/<ip>127.0.0.1<\\/ip>(\\n.*4000.*)/<ip>0.0.0.0<\\/ip>\\1/" /usr/something.conf'
Run Code Online (Sandbox Code Playgroud)
好像python正在添加一个额外的\.有没有办法防止这种情况,以便我可以像使用Popen一样运行命令?
此外,为简化起见,我将其排除在示例之外,但实际上这是在传递给Popen之前将其包装在SSH调用中,所以是的......它确实需要用Popen和完成sed.
这里参考的是字符串经过的完整步骤链...
def _formatCmd(cmdString, host=None, user=None, keyfile=None):
cmd = []
if host:
cmd.append('ssh')
keyfile = keyfile or getKeyFile()
if keyfile:
cmd.append('-i')
cmd.append(keyfile)
cmd.append("%s@%s" % (user, host))
cmd.append(cmdString)
else:
cmd += cmdString.split()
return cmd
def runCmd(host, user, cmd, timeout=None, cleanup=False):
try:
cmd = _formatCmd(cmd, host=host, user=user)
except:
pass
#create cmd and add it to list of running cmds
proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
runningCmds[proc.pid] = proc
t = threading.Timer(timeout, proc.kill)
t.start()
stdout, stderr = proc.communicate()
t.cancel()
del runningCmds[proc.pid]
return (proc.returncode, stdout, stderr)
cmd = r'sudo sed -irn "1!N; s/<ip>127.0.0.1<\/ip>(\n.*4000.*)/<ip>0.0.0.0<\/ip>\1/" /usr/something.conf'
runCmd('1.1.1.1', 'username', cmd)
Run Code Online (Sandbox Code Playgroud)
返回的确切错误消息是:
sed: -e expression #1, char 59: invalid reference \\1 on `s' command's RHS
Run Code Online (Sandbox Code Playgroud)
问题在于 shell 正在执行自己的解释/转义。我在使用 cygwin 时发现了类似的东西(在 cygwin 的情况下,shell 是 bash)。
事实上,您收到错误:
sed: -e expression #1, char 59: invalid reference \\1 on `s' command's RHS
Run Code Online (Sandbox Code Playgroud)
意味着()问题出在括号上,而不是 的转义\1。本质上,它无法找到该组,因此您需要转义括号\(...\)。
要找到原因,技巧是使用echo调试发送的内容:
将正则表达式简化为一组和匹配。就像是:
s/(one)/\1\1/
Run Code Online (Sandbox Code Playgroud)
其中输入字符串为“one”,预期输出为oneone
更改您的cmdtoecho以便传递给 shell 的内容是echo s/(one)/\1\1/
我猜你会看到类似的东西bash: syntax error near unexpected token '('。这给了我们线索。基本上,我们需要转义括号。
所以现在尝试一下echo s/\(one\)/\1\1。就我而言,我看到类似的东西
s/(one)/\1\1
Run Code Online (Sandbox Code Playgroud)如果运气好的话,你应该能够将它应用到你有问题的表达上。
最简单的方法可能是使用强引号(将命令放在单引号中),它告诉 bash 不要解释字符串,尽管您可能仍然需要转义括号()。
顺便说一句,对于 cygwin 来说,事情需要两次转义,所以实际正确的表达式是:
sed s/\\\(one\\\)/\\1\\1/
Run Code Online (Sandbox Code Playgroud)
所以
echo one | sed s/\\\(one\\\)/\\1\\1/
Run Code Online (Sandbox Code Playgroud)
给出
oneone
Run Code Online (Sandbox Code Playgroud)
使用强引用的等效项是:
echo one | sed 's/\(one\)/\1\1/'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
230 次 |
| 最近记录: |