Print lines based on line number and specified condition

Hi,

I have a file like below.

1,2,3,4,5,6,7,8,9

I would like to print or copied to a file based of line count in perl

If I gave a condition 1 to 3 then it should iterate over above file and print 1 to 3 and then again 1 to 3 etc.

output should be

1,2,3
4,5,6
7,8,9

Hello Anjan,

Following may help you in same.

awk -F, '{for(i=1;i<=NF;i++){{S=S?S OFS $i:$i} if(i%3==0){print S;S=""}}}' OFS=, Input_file

Output will be as follows.

1,2,3
4,5,6
7,8,9

EDIT: I am sorry Jim, seems we have posted on same time, if possible kindly delete my post, as you have OP a question.

Thanks,
R. Singh

What have you tried so far?

I have tried it in perl.

#!/usr/bin/perl

use warnings;
use strict;

my @result;

my $filename = "new_num.txt";

my $i;
unlink $filename;

#START:
while(<>) {

$_ =~ s/,/\n/g;

if (($. == 1) .. ($. == 3)) {

#$_ =~ s/^ //g;

push (@result,$_);


print "@result";

foreach $i (@result) {

$i =~ s/\n/,/g;

open FILE,">>$filename" or die "Cannot read the file $filename: $!\n";

print FILE "$i";

#print FILE "\n";

@result = ();


#goto START;

} 

ravinder singh can you please explain me your awk code.

input=( {a..z} )
C=0
count=0
limit=3
max=${#input[@]}

while [[ $C -lt $max ]];do
	while [[ $count -lt $limit ]];do
		out+=" ${input[$C]}"
		C=$((C+1))
		count=$((count+1))
	done
	echo "$out" ; out=""
	count=0
done
sh ~/file1.txt 
 a b c
 d e f
 g h i
 j k l
 m n o
 p q r
 s t u
 v w x
 y z 

Hope this helps

its not printing entire contents in a file. If a file has 1,2,3,4,5,6,7.

When I use awk code given by ravindersingh its giving output as

awk -F, '{for(i=1;i<=NF;i++){{S=S?S OFS $i:$i} if(i%3==0){print S;S=""}}}' OFS=, Input_file
1,2,3
4,5,6

not printing 7

Hello Anjan1,

Kindly try following and let me know if this helps.

xargs -d"," -n3 Input_file

Output will be as follows.

1 2 3
4 5 6
7

Thanks,
R. Singh

awk -F"," 'BEGIN{c=3} {for (i=1;i<=NF;i++) { printf i%c ? i!=NF ? $i FS : $i"\n" :  $i"\n"}}' filename

Try:

tr , '\n' < file | paste -d, - - -

Not so elegant as some of the other solutions...but your code preference might be Perl.
With this example, you can give the number of output columns on the command line (optional).
The output goes to screen and file (./result.txt).

#!/usr/bin/perl

use warnings;
use strict;

my @result;
my $i;
my $line;
my $cols;

## Usage: command [number of columns]
if ( ! $ARGV[0] ) {
    $cols = 3;     # defaults to 3 columns if none given
} else {
    $cols = $ARGV[0];
}

my $infil = "new_num.txt";
my $outfil = "result.txt";
open ( my $fin, '<', "$infil" ) or die "Cannot read the file $infil: $!\n";
open ( my $fout, '>', "$outfil" ) or die "Cannot read the file $outfil: $!\n";

#START:
while ( $line = <$fin> ) {
    chomp ( $line );
    @result = split (",", $line);
    my $sz = $#result;
    foreach (@result) {
        $i += 1;
        print ($_);
        print $fout ($_);
        if ( $i % $cols != 0 ) {
            print (",") if not ( $i > $sz );
            print $fout (",") if not ( $i > $sz );
        }else{
            print ("\n");
            print $fout ("\n");
        }
    }
    if ( $i % $cols ) {
        print ("\n");
        print $fout ("\n");
    }
    $i = 0;
}
close $fout;
close $fin;

#  output
# (3 cols)
# ~~~~~~
# 1,2,3
# 4,5,6
# 7,8,9

# (multi-line)
# ~~~~~~
# a,b,c
# d,e,f
# g,h,i
# j,k,l
# m,n,o
# p,q,r
# s,t,u
# v,w,x
# y,z
# 0,1,2
# 3,4,5
# 6,7,8
# 9
# A,B,C
# D,E,F

Multi-line data as in Don Cragun's post (#11)

a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
0,1,2,3,4,5,6,7,8,9
A,B,C,D,E,F

Six column output...

a,b,c,d,e,f
g,h,i,j,k,l
m,n,o,p,q,r
s,t,u,v,w,x
y,z
0,1,2,3,4,5
6,7,8,9
A,B,C,D,E,F

I assume Ravinder didn't reply to this because you pointed out that it didn't work correctly if the number of input fields wasn't an exact multiple of the number of desired fields on each output line (and he gave you an xargs solution that worked as you requested).

Here is a slightly modified version of his script that will print the missing data at the end of an input line and allows you to set the desired number of output fields (as in ongoto's perl script):

#!/bin/ksh
FieldsPerLine=${1:-3}			# Set the number of fields to be placed
					# on each output line with a default of
					# 3 if no operands are given.
awk -F, -v fpl="$FieldsPerLine" '	# Set input field separator to comma and
					# set "fpl" to the number of fields to put
					# on each output line.
{	for(i=1;i<=NF;i++){		# For each input field...
		S=((S!="")?S OFS $i:$i)	# If string "S" is not an empty string,
					# set string "S" to the current 
					# contents of "S" followed by the 
					# output field separator followed by the
					# contents of the current field; 
					# otherwise, set string "S" to the 
					# contents of the current field.
		if(i%fpl==0){		# If the current field # is evenly
					# divisible by the specified number of
					# fields per output line...
			print S;S=""	# Print the current contents of the
					# string "S" and clear the contents of
					# "S".
		}
	}
	if(NF%fpl){			# If the number of fields on this input
					# line is not evenly divisible by the
					# specified of fields per output line...
		print S;S=""		# Print the remaining fields for this
					# line and clear the contents of "S".
	}
}' OFS=, Input_file			# Set output field separator to comma
					# and specify the input file to be
					# processed.

The code shown in red is what I changed from Ravinder's original script:

  • The FieldsPerLine shell variable and the fpl awk variable processing allows you to specify the desired number of output fields/line instead of always using the default value (3).
  • The change from S=S?S OFS $i:$i) to: S=((S!="")?S OFS $i:$i) corrects a bug that will only be seen if the 1st field on an output line was from an input field that was a string of one or more zeroes.
  • The if statement added after the for loop takes care of the missing output lines from input lines that do not contain an even multiple of the number of fields desired in output lines.

This was written and tested using the Korn shell, but it will also work with any other shell that recognizes basic POSIX parameter expansion requirements (such as bash ). As with any standard awk script, if you want to try this on a Solaris/SunOS system, change awk to /usr/xpg4/bin/awk , /usr/xpg6/bin/awk , or nawk .

If Input_file contains:

a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
0,1,2,3,4,5,6,7,8,9
A,B,C,D,E,F

the default output produced by this script is:

a,b,c
d,e,f
g,h,i
j,k,l
m,n,o
p,q,r
s,t,u
v,w,x
y,z
0,1,2
3,4,5
6,7,8
9
A,B,C
D,E,F

and if run with a different requested number of fields per output line such as with ./splitline 5 , it produces the output:

a,b,c,d,e
f,g,h,i,j
k,l,m,n,o
p,q,r,s,t
u,v,w,x,y
z
0,1,2,3,4
5,6,7,8,9
A,B,C,D,E
F
2 Likes