0

I know I can run commands against a match in sed like so:

$ cat file
line1
line2
line3
line4

$ sed -e "/^line2/ s/^/# /" file
line1
# line2
line3
line4

Is it possible to run multiple commands, say s/^/#/ and s/$/ # invalid/ on the same match?

I tried adding them both but I get an error:

$ sed -e "/^line2/ s/^/# / s/$/ # /" file
sed: -e expression #1, char 18: unknown option to `s'

I tried using ; but that seems to discard the initial match and execute on every line in the input:

$ sed -e "/^line2/ s/^/# / ; s/$/ # /" file
line1 #
# line2 #
line3 #
line4 #
Inian
  • 80,270
  • 14
  • 142
  • 161
IMTheNachoMan
  • 5,343
  • 5
  • 40
  • 89
  • Possible duplicate of [Combining two sed commands](https://stackoverflow.com/questions/7657647/combining-two-sed-commands) – tripleee Feb 05 '19 at 06:30
  • 1
    @Tiw I am sorry, I should have put in the question that I tried `{}` blocks but could not get it to work. However, I now realize what I was doing wrong and got it working with: `sed -e "/^line2/ { s/^/# / ; s/$/ # asdf/ }" file`. – IMTheNachoMan Feb 05 '19 at 11:56
  • @tripleee It is a duplicate in that they both want to combine commands but mine is unique in that I wanted to match a pattern then apply commands like `s///` or `a TEXT`. – IMTheNachoMan Feb 05 '19 at 11:57

4 Answers4

3

EDIT2: In case you are looking very specifically to execute multiple statements when a condition has met then you could use {..} block statements as follows.(Just saw @Tiw suggested same thing in comments too.)

sed '/^line2/ {s/^/#/; s/$/ # invalid/}'  Input_file


EDIT: Adding 1 more solution with sed here. (I am simply taking line which is starting with line2 in a memory buffer \1 then simply while putting substituted/new_value adding # before it and appending # invalid after it)

sed '/^line2/s/\(.*\)/# \1 # invalid/'  Input_file


Could you please try following.

sed "/^line2/ s/^/# /;/^line2/s/$/ # invalid/"  Input_file

What is happening in your attempt, you are simply doing substitution which is happening on each line irrespective of either it starts from line2 or not, so when you give that condition before substitution it should work then.

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
1

You can try with extended regexp:

sed -r -e '/^line2/ s/(.*)/# \1 #/' file
user2468968
  • 286
  • 3
  • 9
  • The `#` was just an example. Ideally I want to run multiple commands like `a TEXT` and `i TEXT` and `s///` and `d`, etc... – IMTheNachoMan Feb 05 '19 at 11:58
1

You don't need multiple commands, just replace lines starting with line2:

sed "s/^line2.*/# & #/" file
SLePort
  • 15,211
  • 3
  • 34
  • 44
0

This might work for you (GNU sed):

sed '/^line2/!b;s/^/.../;s/$/.../' file

Here the regexp is negated by using the ! command and the b command by itself branches to the end of all sed commands. Perhaps as easier example would be:

sed ' /^lines/bjumphere;bjumpthere;:jumphere;s/^/.../;s/$/.../;:jumpthere' file

Of course the above can also be written:

sed '/^line2/{s/^/.../;s/$/.../}' file

When writing one liners that end in a newline (such as i, a, c, r, R, w and W commands) and further commands are wanted, the -e option may be invoked for each part of the sed script, an example:

sed -e '/^line2/{i\a couple of lines\ninserted before "line2"' -e '}' file

Also could be written:

sed '/^line2/i\a couple of lines\ninserted before "line2"' file

if there are no subsequent sed commands to be executed, however if line2 needed to be deleted too:

sed -e '/^line2/b;!i\a couple of lines\ninserted before "line2 then line2 deleted"' -e 'd' file

However a better way would be to use the c command.

sed '/^line2/c\a line changed and a line\nappended for "line2"' file
potong
  • 55,640
  • 6
  • 51
  • 83