kashiff007
kashiff007

Reputation: 386

Replace in every nth line starting from a certain line

I want to replace on every third line starting from second line using sed.

Input file
A1
A2
A3
A4
A5
A6
A7
.
.
.

Expected output
A1
A2
A3
A4_edit
A5
A6
A7_edit
.
.
.

I know there are many solution releted to this is available on stack but for this specific problem, I was unable to find.

My try:

sed '1n;s/$/_edit/;n'

This only replacing on every second line from the beginning.

Upvotes: 1

Views: 3203

Answers (4)

Jon
Jon

Reputation: 3671

Something like this?

$ seq 10 | sed '1b ; n ; n ; s/$/_edit/'
1
2
3
4_edit
5
6
7_edit
8
9
10_edit

This breaks down to a cycle of

  • 1b if this is the first line in the input, start the next cycle, using sed default behaviour to print the line and read the next one - which skips the first line in the input
  • n print the current line and read the next line - which skips the first line in a group of three
  • n print the current line and read the next line - which skips the second line in a group of three
  • s/$/_edit/ substitute the end of line for _edit on the third line of each group of three
  • then use the default sed behaviour to print, read next line and start the cycle again

If you want to skip more than one line at the start, change 1b to, say, 1,5b.

As Wiktor Stribiżew has pointed out in the comments, as an alternative, there is a GNU range extension first~step which allows us to write

sed '4~3s/$/_edit/'

which means substitute on every third line starting from line 4.

Upvotes: 3

Håken Lid
Håken Lid

Reputation: 23084

You can use seds ~ step operator.

sed '4~3s|$|_edit|'

~ is a feature of GNU sed, so it will be available in most (all?) distros of Linux. But to use it on macOS (which comes with BSD sed), you would have to install GNU sed to get this feature: brew install gnu-sed.

Upvotes: 2

Jotne
Jotne

Reputation: 41460

Another awk

awk 'NR>3&&NR%3==1{$0=$0"_edit"}1' file
A1
A2
A3
A4_edit
A5
A6
A7_edit
A8
A9
A10_edit
A11
A12
A13_edit

NR>3 Test if line is larger then 3
NR%3==1 and every third line
{$0=$0"_edit"} edit the line
1 print everything

Upvotes: 2

RavinderSingh13
RavinderSingh13

Reputation: 133770

In case you are ok with awk, try following.

awk -v count="-1" '++count==3{$0=$0"_edit";count=0} 1' Input_file

Append > temp_file && mv temp_file Input_file in case you want to save output into Input_file itself.

Explanation:

awk -v count="-1" '     ##Starting awk code here and mentioning variable count whose value is -1 here.
++count==3{             ##Checking condition if increment value of count is equal to 3 then do following.
  $0=$0"_edit"          ##Appending _edit to current line value.
  count=0               ##Making value of count as ZERO now.
}                       ##Closing block of condition ++count==3 here.
1                       ##Mentioning 1 will print edited/non-edited lines.
' Input_file            ##Mentioning Input_file name here.

Upvotes: 3

Related Questions