Cat Savage
Cat Savage

Reputation: 21

How do I make this sed replacement case insensitive

I need to modify a script, and I need to add a line before the first match of a "begin" statement with the string "some text" on its own line. The following command does the job, but I cannot figure out how to make it case insensitive:

sed -i '0,/begin/s//some text\nbegin/' filename

This fails:

sed -i '0,/begin/s//some text\nbegin/i' filename

...with the error sed: -e expression #1, char 45: cannot specify modifiers on empty regexp

How can I make this replacement case insensitive?

Upvotes: 2

Views: 153

Answers (1)

Benjamin W.
Benjamin W.

Reputation: 52132

You're using an address range including line 0, so I guess you're using GNU sed. In that case, there is an extension to the regex used in the address, namely an I modifier:

$ printf 'Text\nBegin\n' |sed '0,/begin/I s//some text\nbegin/'
Text
some text
begin

This matches case insensitively, but still always inserts a lowercase "begin". To avoid changing it, you can use

$ printf 'Text\nBegin\n' | sed '/begin/I i some text'

/begin/I matches case insensitively, i inserts the text following it on a separate line before the matching line.

To make sure this only modifies the first instance as in your example, you can combine it with an address range again:

printf 'Text\nBegin\n' | sed '0,/begin/I{/begin/I i some text
}'

Sed gets a little finicky with i and line breaks combined with braces, so inserting an actual linebreak seems to be required. The classical way is to have the argument to the i command on a completely separate line:

sed '0,/begin/I{
/begin/I i\
some text
}'

Or, briefer (hat tip to Etan Reisner):

sed '0,/.*begin/I s//some text\n&/'

This captures everything on the line containing begin and inserts "some text" with a newline before the matched string, preserving whatever might be on that line already.

Upvotes: 1

Related Questions