3

Id like to do do the following substitution

sed 's/$/)/' python2.py

with the condition that a line contains print( but it may not contain print(""".

A line that it should not match would be

print("""Some multi line text etc... 

While lines like this should be matched

print("Some single line text"

Now its easy to match one or to exclude the other but i fail to combine both conditions into one command. For example

sed -ne '/print(/s/$/)/p' python2.py

Does match all lines with print( but also the ones which i would like to omit with print(""". On the other hand i can skip all lines with print(""" with

sed -ne /print("""/! s/$/)/p python2.py

But that includes all other lines even those without print(. Is there any way to combine both conditions such that the substition is only applied when both conditions are true for a line ?

As a note :

I am aware that i can do two sed runs where i first do the substitutions for all print( lines and then do a second sed run where i remove the newly substituted ) only in the print(""" lines. I'd like to know if it is possible to do it in one go so that is not an answer that i am looking for.

Hans Wurst
  • 227
  • 2
  • 15

3 Answers3

3

You may use this sed that ignore lines that already have a closing ):

cat file
print("""Some multi line text etc...
print("Some single line text"
print("Some single ""line text"
print("Some single line text")

sed '/print("""/!s/print(".*[^)]$/&)/' file
print("""Some multi line text etc...
print("Some single line text")
print("Some single ""line text")
print("Some single line text")

Pattern print(".*[^)]$ matches a line with test from print(" with a non-) character in the end. &) places ) at the end of matching pattern.

anubhava
  • 761,203
  • 64
  • 569
  • 643
1

With GNU sed, you can use

sed '/print("""/!{/print("/s/$/)/}' file > newfile

See the online demo.

Details:

  • /print("""/! - if print(""" is found, skip the line
  • {/print("/s/$/)/} - else, if line contains print(", replace the end of line with ).
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    Nothing here is hard to do in standard `sed` either. Some `sed` dialects will insist on statement terminators before or after the curly brackets. You can avoid that by changing the `!` to a `b` and then you don't need the curlies. – tripleee Jan 18 '21 at 17:13
  • Works as intended. The curly braces syntax was what i was missing. – Hans Wurst Jan 18 '21 at 17:16
  • Aha, `sed '/print("""/b;/print("/s/$/)/'` will work, too. – Wiktor Stribiżew Jan 18 '21 at 17:17
1

Is this all you're trying to do?

$ cat file
print("""Some multi line text etc...
print("Some single line text"

$ sed 's/print("[^"].*/&)/' file
print("""Some multi line text etc...
print("Some single line text")

If not then please edit your question to show more truly representative sample input/output that includes cases this doesn't work for.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185