11

I am wondering whether there is a simple way to operate on certain lines with preassigned line numbers.

Let's say I want to output the 1st, 7th, 14th and 16th lines of a file, I can simply do

sed -n '1p;7p;14p;16p' input_file

but this gets more complicated when the operation is not just printing, and I don't want to write the same long command 4 times (and yes, I know I can construct this long sed command by substituting the same bash variable 4 times, but that's not ideal enough ...) , i.e.

sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file

Is there a way to do the operation on these specific lines of my file? I am expecting something like,

sed -n '1,7,14,16p'

which certainly will not work in the current form.

Any help will be appreciated. "No, it is not possible." with explanations is also an answer that I will accept.

1

3 Answers 3

14

You can use branches:

sed '
  1b1
  7b1
  14b1
  16b1

  # for the rest to be left alone, branch off (or delete them with "d"):
  b

  :1
  long_command'

(note that you can also add some 20,25b1 line ranges, or /re/b1 to include lines that match the re).

Or you could use awk:

awk 'NR == 1 || NR == 7 || ... {stuff}'

Or using a hash:

awk -v l=1,7,14,16 '
  BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}

  NR in lines {stuff}'

(or BEGIN{lines[1]lines[7]lines[14]lines[16]} if there aren't too many)

2
  • Thank you, never thought of branches ... It just seem to be the ideal tool to use in this case. Commented Jan 15, 2018 at 16:44
  • how do use branches like this in sed with a search pattern? like say I wanna match or delete a pattern after the nth line?
    – qodeninja
    Commented Jul 28, 2018 at 20:47
3

Simply invert your selection and delete it:

sed '2,6d;8,13d;15d;17,$d;long_command'
1
  • This is also a nice solution although a little harder for handling line numbers that are read from stdin, for example. Commented Jan 15, 2018 at 17:08
1

First variant:

You can use this trick:

sed -nf <(printf '%dp\n' 1 7 14 16)

-f script-file - add the contents of script-file to the commands to be executed.

Testing

seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)

Output

1
7
14
16

Second variant:

In the beginning, the auxiliary sed is used for filtering only needed lines from the file, then these lines piped to the main sed with the long command.

sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'

You must log in to answer this question.

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