3

While going through a shell script I came across the line

sed '1{/^$/d}' $file1 >> $file2

What is the significance of sed '1{/^$/d}' here?

1
  • While it removes empty lines lines that are marked as $ when running sed -n l file1 it won't remove lines that have ...spaces... in them. Therefore you could consider sed '1{/^$/d;/\s*/d;}' file1 Jun 15, 2022 at 8:07

2 Answers 2

5

Remove line 1 if it's empty....

  • 1{ - if we're on line 1
  • /^$/ - and it's an empty line
  • d - delete the line
  • } - end of condition

Example below.

$ cat x1

Hello
World
$ sed '1{/^$/d}' x1 >x2
$ cat x2
Hello
World
$
5

The GNU sed expression

1{/^$/d}

which is more portably written

1{/^$/d;}

or

1 {
    /^$/ d
}

is in two parts:

  1. 1 {...}
  2. /^$/ d

The first part triggers the command within braces if the current line is the first line of input.

The second part triggers the d command if the current line is empty, i.e. if the start of the line, ^, is immediately followed by the end of the line, $. The d command discards the current input and immediately starts the next cycle (which means it skips to the following line of input and starts evaluating the expression from the very start).

Both 1 and /^$/ are addresses that affect what lines the subsequent command will be applied to.

In short, your sed command deletes the first line of input if it's empty while avoiding deleting any other empty line.

The expression

/^$/ { 1 d; }

would have done the same thing but would require sed to perform a regular expression match on each line of input and would therefore potentially be more expensive (although it's questionable if you would notice any difference unless your input was huge and your computer very slow).


Apart from that, you should most likely quote the variables in your command, and the since we don't know what's in $file1, we'd better protect the command from accidentally interpreting the value as a set of options if it starts with a dash:

sed -- '1 { /^$/ d; }' "$file1" >>"$file2"

or,

sed -e '1 { /^$/ d; }' -- "$file1" >>"$file2"

or, make sed read from standard input,

sed '1 { /^$/ d; }' <"$file1" >>"$file2"

See also

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .