shell insert a line every n lines

2019-05-06 17:07发布

问题:

I have two files and I am trying to insert a line from file2 into file1 every other 4 lines starting at the beginning of file1. So for example:

file1:

line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10

file2:

50
43
21

output I am trying to get:

50
line 1
line 2
line 3
line 4
43
line 5
line 6
line 7
line 8
21
line 9
line 10

The code I have:

while read line
do
    sed '0~4 s/$/$line/g' < file1.txt > file2.txt
done < file1.txt

I am getting the following error:

sed: 1: "0~4 s/$/$line/g": invalid command code ~

回答1:

The following steps through both files without loading either one into an array in memory:

awk '(NR-1)%4==0{getline this<"file2";print this} 1' file1

This might be preferable if your actual file2 is larger than what you want to hold in memory.

This breaks down as follows:

  • (NR-1)%4==0 - a condition which matches every 4th line starting at 0
  • getline this<"file2" - gets a line from "file2" and stores it in the variable this
  • print this - prints ... this.
  • 1 - shorthand for "print the current line", which in this case comes from file1 (awk's normal input)


回答2:

It is easing to do this using awk:

awk 'FNR==NR{a[i++]=$0; next} !((FNR-1) % 4){print a[j++]} 1' file2 file1

50
line 1
line 2
line 3
line 4
43
line 5
line 6
line 7
line 8
21
line 9
line 10
  • While processing first file in input i.e. file2, we store each line in array with key as an incrementing number starting with 0.
  • While processing second file in input i.e. file1, we check if current record # is divisible by 4 using modulo arithmetic and if it is then insert a line from file2 and increment the index counter.
  • Finally using action 1, we print lines from file1.


回答3:

This might work for you (GNU sed):

sed -e 'Rfile1' -e 'Rfile1' -e 'Rfile1' -e 'Rfile1' file2

or just use cat and paste:

cat file1 | paste -d\\n file2 - - - -


回答4:

another alternative with unix toolchain

$ paste file2 <(pr -4ats file1) | tr '\t' '\n'

50
line 1
line 2
line 3
line 4
43
line 5
line 6
line 7
line 8
21
line 9
line 10


回答5:

Here's a goofy way to do it with paste and tr

paste file2 <(paste - - - - <file1) | tr '\t' '\n'

Assumes you don't have any actual tabs in your input files.



标签: file shell awk