【问题标题】:Create string with backslashes for use by sed创建带有反斜杠的字符串以供 sed 使用
【发布时间】:2014-10-23 23:37:51
【问题描述】:

我正在 python 中创建一个命令字符串,需要使用 pexpect 在主机上执行。我希望在主机上运行的 sed 命令如下:

sed -i 's/\(panic=30\)/\1 my_cool_option/g' /boot/bootrc

如何在 python 中创建一个保留反斜杠的变量?最初,我尝试过

bootrc = '/boot/bootrc'
param = 'ignorefs'
cmd = "sed -i 's/\(panic=30\)/\\1 {}/g' {}".format(param, bootrc)
self.runExpectCmd(cmd)

当我在 python shell 中检查上述代码时,它看起来还不错:

>>> bootrc = '/boot/bootrc'
>>> param = 'ignorefs'
>>> cmd = "sed -i 's/\(panic=30\)/\\1 {}/g' {}".format(param, bootrc)
>>> print cmd
sed -i 's/\(panic=30\)/\1 ignorefs/g' /boot/bootrc

但是,当我逐步通过 pdb 了解代码失败的原因时,cmd 设置为

(Pdb) p cmd
"sed -i 's/\\(panic=30\\)/\\1 ignorefs/g' /boot/bootrc"

我不知道如何生成正确的字符串来执行 sed 命令。

谢谢

【问题讨论】:

  • 我得到了替换来处理这个:cmd = "perl -pi -e 's/(panic=30)/\\1 foobar/g' bootrc".format(param, bootrc) 我仍然想了解如何生成一个 sed 可以使用的字符串。
  • 原始字符串? r'...'?

标签: python


【解决方案1】:

第一次阅读您的问题时,我感到很困惑,但请查看string literals 页面

您可能知道,python 使用反斜杠字符\ 作为转义字符。所以要在字符串文字中包含一个新行,我们输入

s = 'hello\nworld'

如果我们想要一个实际的反斜杠,我们使用双反斜杠

s = '\\'

如果反斜杠后面的字符与转义序列不匹配,则反斜杠保持原样

s = '\ ' # space doesn't match any escape sequence, so you get to keep the backslash

这就是你的\( 所发生的事情 - 你最终得到<backslash><open parnes>

但是\1 确实匹配转义序列 - 它是字符的八进制表示的文字。所以你得到的是<0x01>,而不是<backslash>1

当您在 pdb 中使用 p cmd 时,它会打印字符串的 repr,这恰好对不可打印的字符使用反斜杠转义。这与在 python shell 中使用 print cmd 不同。

python shell:
>>> print '\\'
\

pdb:
(Pdb) p '\\'
'\\'

Pdb 向您显示您有一个反斜杠。类似于

>>> print repr('\\')
'\\'

所以当你说

(Pdb) p cmd
"sed -i 's/\\(panic=30\\)/\\1 ignorefs/g' /boot/bootrc"

那里的所有双反斜杠对都是单反斜杠字符。与您在 cmets 中的工作示例的不同之处在于您在打开/关闭括号前面有文字反斜杠。

最后,如果你不想担心反斜杠转义,你可以使用原始字符串

>>> s = r"sed -i 's/\(panic=30\)/\1 my_cool_option/g' /boot/bootrc"
>>> print s
sed -i 's/\(panic=30\)/\1 my_cool_option/g' /boot/bootrc
>>> print repr(s)
"sed -i 's/\\(panic=30\\)/\\1 my_cool_option/g' /boot/bootrc"

【讨论】:

  • Peter:感谢您冗长的回复,尤其是解释 pdb 的输出。我的 sed 命令按预期工作。
【解决方案2】:

我看到您的问题已得到解答,但为了将来参考,如果您有一个带有反斜杠的字符串并且您希望 确定 它包含您认为应该包含的内容,您可以浏览它逐个字符并打印它,例如

#! /usr/bin/env python

mystring = "this\nis\t a \complicated\\string"
print repr(mystring), len(mystring)
for i,v in enumerate(mystring):
    print "%2d: %-4r %02x" % (i, v, ord(v))

输出

'this\nis\t a \\complicated\\string' 30
 0: 't'  74
 1: 'h'  68
 2: 'i'  69
 3: 's'  73
 4: '\n' 0a
 5: 'i'  69
 6: 's'  73
 7: '\t' 09
 8: ' '  20
 9: 'a'  61
10: ' '  20
11: '\\' 5c
12: 'c'  63
13: 'o'  6f
14: 'm'  6d
15: 'p'  70
16: 'l'  6c
17: 'i'  69
18: 'c'  63
19: 'a'  61
20: 't'  74
21: 'e'  65
22: 'd'  64
23: '\\' 5c
24: 's'  73
25: 't'  74
26: 'r'  72
27: 'i'  69
28: 'n'  6e
29: 'g'  67

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 1970-01-01
    • 2022-01-23
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    相关资源
    最近更新 更多