replay
replay

Reputation: 3819

Sed insert string at first line of file if the first line matches pattern

I have an sed question to which I couldn't find the answer anywhere yet:

I have a bunch of files, some of them start with the string ### and some don't. In every file which starts with ### I would like to insert some multi-line string before the current first line.

f.e. If a file looks like

### the first line

abc cba jfkdslfjslkd

I want the multi line string to get inserted at the top

my
multi
line
string

### the first line

abc cba jfkdslfjslkd

Nothing else in the file should get modified.

If a file does not start with ### then I don't want to edit it.

Upvotes: 2

Views: 657

Answers (3)

user7712945
user7712945

Reputation:

tried on gnu sed and bash

$ a='my\nmulti\nline\nstring'; echo -e $a
my
multi
line
string

$  sed -Ee "0,/^###/{/^###/i$a" -e '}' file*

my
multi
line
string
### the first line

abc cba jfkdslfjslkd

Upvotes: 0

Alex Harvey
Alex Harvey

Reputation: 15502

This may be a simpler solution in sed:

Input:

▶ string='my\nmulti\nline\nstring\n'
▶ cat FILE 
### the first line

abc cba jfkdslfjslkd

### other lines

Solution:

▶ gsed -e '1{/^###/i\' -e "$string" -e '}' FILE
my
multi
line
string

### the first line

abc cba jfkdslfjslkd

### other lines"

Explanation:

  • Use of multiple -e allows us to avoid interpolating strings into the sed command.
  • The GNU alternative form of i\ command as noted in the GNU manual.

Upvotes: 0

John1024
John1024

Reputation: 113994

Using sed

First let's define your string:

$ s='my\nmulti\nline\nstring\n\n'

Now, let's run a sed command:

$ sed "1s/^###/$s&/" File
my
multi
line
string

### the first line

abc cba jfkdslfjslkd

How it works:

  • 1s/old/new/ substitutes new for old but only if old occurs on the first line.

  • 1s/^###/$s&/ substitutes the string $s in front of ### if the first line starts with ###.

Warning: The string s should not contain any sed-active characters. If the string s is not under your control, this is a security violation.

Using awk

Awk has sensible handling of variables and this avoids the security problem.

$ s='my\nmulti\nline\nstring\n'
$ awk -v string="$s" 'NR==1 && /^###/ {print string} 1' File
my
multi
line
string

### the first line

abc cba jfkdslfjslkd

Upvotes: 2

Related Questions