How to pass a line number variable to sed, to delete all lines after that line

Viewed 468

I am having trouble passing this variable into sed in a bash script. I was able to successfully do the reverse of what I am asking (delete all lines prior to a specified line number) following this syntax.

    sed "1,${line_number}d"

but trying to recreate a similar answer to delete all lines after a line number continuously gives me errors. I have tried follwing:

    sed "${line_number},$d" #results in unexpected comma
    sed "|${line_number}|,|$d|" #trying to use a separator gives me an error for missing command

I'm not sure why the first would work but the second one would not. Any help appreciated!

2 Answers

In sed "${line_number},$d" the second $ is also interpret by bash. Bash sees $d and expands it, probably to the empty string if you didn't assign any value to d. You effectively execute something like sed '5,' which explains the unexpected comma.

To fix the problem, escape the second $:

sed "$line_number,\$d"

By the way, instead of deleting the lines starting at $line_number you can also extract the $((line_number-1)) first lines which is probably faster:

head -n "$((line_number-1))"

I suggest always checking what real literal text you just coded in the string literal with simple echo:

line_number=3
echo "${line_number},$d"
# => 3,

This reveals the secret of the unexpected ,.

Then, only double quote the variables, the rest of sed command is better quoted with single quotes:

sed "${line_number}"',$d' file > newfile

"${line_number}" is inside double quotes and thus the variable expansion will take place, the rest is inside single quotes, no variable expansion will thus occur.

See an online test:

#!/bin/bash
line_number=3
s='Line 1
Line 2
Line 3
Line 4
Line 5'
echo "${line_number},$d"
sed "${line_number}"',$d' <<< "$s"

Output:

3,
Line 1
Line 2
Related