Create backslash string for sed use

I am creating a command line in python to be executed on a node using pexpect. The sed command I want to run on the host looks like this:

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

      

How do I create a variable in python that keeps the backslash as it is? I originally tried

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

      

When I checked this code in the python shell, it looked quite normal:

>>> 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

      

However, when I stepped through pdb to understand why the code failed, the cmd was set to

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

      

I don't understand how to create the correct line to execute the sed command.

thank

+1


source to share


2 answers


This confused me on the first reading of your question, but look at the string literals page

As you probably know, python uses the backslash character \

as the escape character. So, to include a newline in a string literal, type

s = 'hello\nworld'

      

If we want the actual backslash we use the double backslash

s = '\\'

      

If the character following the backslash does not match the escape sequence, the backslash is stored as

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

      

This is what happens to yours \(

- in the end you get<backslash><open parnes>

However, it \1

matches an escape sequence - it is a literal for the octal representation of a character. So instead <backslash>1

you got <0x01>

.



When used p cmd

in pdb, it prints a repr

string, which is used to use a backslash for non-printable characters. This is different from using it print cmd

in the python shell.

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

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

      

Pdb shows you that you have a backslash. Similarly

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

      

So when you said

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

      

All double backslash pairs have single backslashes. The difference with your working example in the comments is that you have literal backslashes in front of your open / closed parens.

Finally, if you don't want to worry about escaping backslashes, you can use raw strings

>>> 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"

      

+2


source


I see your question has been answered, but for future reference, if you have a backslash string and want to be sure it contains what you think it should, you can scan its through char to char and print it like

#! /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))

      



Output

'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

      

+1


source







All Articles