Bob
Bob

Reputation: 483

Issue with special characters in Python subprocess

I translated this bash one-liner:

awk '/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1' filename2 > filename1  

into this Python code

with open('filename1', 'w') as f:
    call(['awk', '/\\\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1', 'filename2'], stdout=f)  

The output file, however, is empty, and it is not when I use the bash.

With this:

call(['awk', r"'/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1'"], stdout=f)

I get

awk: '/]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1' awk: ^ invalid char ''' in expression

Sample Input file:

Interval: [ some_value some_value1]:
Interval: [ some_value some_value2]:
some text here1 
some text here2
some text here3
some text here4
Interval: [ some_value some_value3]:
Interval: [ some_value some_value4]:
Interval: [ some_value some_value5]:
Interval: [ some_value some_value6]:
some text here5
some text here6
some text here7
some text here8
Interval: [ some_value some_value7]:
Interval: [ some_value some_value8]:

Sample Output File:

Interval: [ some_value some_value2]:
some text here1
some text here2
some text here3
some text here4
Interval: [ some_value some_value6]:
some text here5
some text here6
some text here7
some text here8

Upvotes: 1

Views: 1881

Answers (1)

spectras
spectras

Reputation: 13552

I bet you have an issue with your string conversion. Python version gives:

>>> print('/\\\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1')
/\\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1

While the shell version gives.

$ echo '/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1'
/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1

You can simplify this kind of stuff using raw string notation:

>>> print(r'/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1')
/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1

From the documentation:

When an r or R prefix is present, backslashes are still used to quote the following character, but all backslashes are left in the string. For example, the string literal r"\n" consists of two characters: a backslash and a lowercase `n'. String quotes can be escaped with a backslash, but the backslash remains in the string; for example, r"\"" is a valid string literal consisting of two characters: a backslash and a double quote

So for your command:

call(['awk', r'/\]:$/{pno=NR;prec=$0;next} pno && !(/^I/ && NR==pno+1){print prec; pno=0} 1', filename2], stdout=f)

Upvotes: 2

Related Questions