ipek
ipek

Reputation: 75

split a file based upon line number

I have a large file that needs to be slitted based on line numbers. For instance , my file is like that:

aaaaaa 
bbbbbb  
cccccc
dddddd
****** //here blank line//
eeeeee
ffffff
gggggg
hhhhhh
*******//here blank line//
ıııııı
jjjjjj
kkkkkk
llllll
******
//And so on...

I need two separate files as such that one file should have first 4 lines, third 4 lines, fifth 4 lines in it and the other file should have second 4 lines, fourth 4 lines, sixth 4 lines in it and so on. how can I do that in bash script?

Upvotes: 0

Views: 1979

Answers (5)

glenn jackman
glenn jackman

Reputation: 246744

Another approach is to treat blank-line-separated paragraphs as the records, and print odd-numbered and even-numbered records to different files:

awk -v RS= -v ORS='\n\n' '{
    outfile = (NR % 2 == 1) ? "file1" : "file2"
    print > outfile
}' file

Upvotes: 1

fedorqui
fedorqui

Reputation: 289495

You can play with the number of the line, NR:

$ awk 'NR%10>0 && NR%10<5' your_file > file1
$ awk 'NR%10>5' your_file > file2
  • If it is 10K + n, 0 < n < 5, then goes to the first file.
  • If it is 10K + n, n > 5, then goes to the second file.

In one line:

$ awk 'NR%10>0 && NR%10<5 {print > "file1"} NR%10>5 {print > "file2"}' file

Test

$ cat a
1
2
3
4

6
7
8
9

11
12
13
14

16
17
18
19

21
22
23
24

26
27
28
29

31
32
33
34

36
37
38
39

41
42
43
44

46
47
48
49

51
$ awk 'NR%10>0 && NR%10<5 {print > "file1"} NR%10>5 {print > "file2"}' a
$ cat file1
1
2
3
4
11
12
13
14
21
22
23
24
31
32
33
34
41
42
43
44
51
$ cat file2
6
7
8
9
16
17
18
19
26
27
28
29
36
37
38
39
46
47
48
49

Upvotes: 2

Ortwin Angermeier
Ortwin Angermeier

Reputation: 6183

Maybe something like that:

#!/bin/bash

EVEN="even.log"
ODD="odd.log"

line_count=0
block_count=0
while read line
do
    # ignore blank lines
    if [ ! -z "$line" ]; then
      if [ $(( $block_count % 2 )) -eq 0 ]; then
        # even
        echo "$line" >> "$EVEN"
      else
        # odd
        echo "$line" >> "$ODD"
      fi
      line_count=$[$line_count +1]
      if [ "$line_count" -eq "4" ]; then
        block_count=$[$block_count +1]
        line_count=0
      fi
    fi
done < "$1"

The first argument is the source file: ./split.sh split_input

Upvotes: 0

Ilya
Ilya

Reputation: 4689

This script prints lines from file 1.txt with indexes 0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, ...

i=0
while read p; do
  if [ $i%8 -lt 4 ]
  then
    echo $p
  fi
  let i=$i+1
done < 1.txt

This script prints lines with indexes 4, 5, 6, 7, 12, 13, 14, 15, ...

i=0
while read p; do
  if [ $i%8 -gt 3 ]
  then
    echo $p
  fi
  let i=$i+1
done < 1.txt

Upvotes: 0

urzeit
urzeit

Reputation: 2909

You can do this with head and tail (which are not be part of the bash itself):

head -n 20 <file> | tail -n 5

gives you the lines 15 to 20.

This is however inefficient, if you want to get multiple sections of your file, since it has to be parsed again and again. In this case I'd prefer some real scripting.

Upvotes: 1

Related Questions