Reputation: 217
Hello I am trying to make a one-liner in perl( or ruby ) that reads data from a file into an array, and prints it in columns with a newline after ever 10nth element.
The file is like this
Name
Course1
Mark1
Course2
Mark2
Course3
Mark3
Course4
Mark4
And should be displayed like this
Name Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4
This is what I have tried to far
perl -ne '@a=split"\n",$_;print join("\t"=>splice@a,0,10)' Data.txt
Upvotes: 0
Views: 283
Reputation: 160551
The data sample is only nine lines, so it won't fit conveniently into a ten-line bucket. I added a placeholder so my text file looks like:
Name Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 ----- Name Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 -----
I'd do it in Ruby something along these lines:
puts ARGF.lines.map(&:chomp).each_slice(10).map{ |a| a.join(' ') }
Which gives me an output like:
Name Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 ----- Name Course1 Mark1 Course2 Mark2 Course3 Mark3 Course4 Mark4 -----
Using tabs instead of spaces is trivial: replace ' '
with "\t"
, but how is left as an exercise for the reader.
map(&:chomp)
strips the trailing line-endings so the fields can exist on one line when printed. each_slice(10)
grabs array elements ten at a time, which results in an array-of-arrays, each sub-array containing ten strings. The final map{ |a| a.join(' ') }
joins the sub-arrays with spaces, or tabs if changed to "\t"
. Alternately, a * ' '
or a * "\t"
could have been used instead of join
, but join
is more commonly used.
Upvotes: 0
Reputation: 385996
That doesn't work because you're splitting on newlines when you read a line at a time. You'd need -0777
to make it work.
You also only print the first 10 elements, so you'd need to introduce a loop.
perl -0777nE'@F = split /\n/; say join "\t", splice @F,0,10 while @F' Data.txt
That begs to take advantage of -a
!
perl -F'\n' -0777naE'say join "\t", splice @F,0,10 while @F' Data.txt
Or we can take a completely different approach. Short and sweet:
perl -pe's/\n/\t/ if $. % 10' Data.txt
If there isn't a multiple of 10 columns, that will end with a trailing tab instead of a newline. Ok, not so good. Then how about
perl -0777pe's/\n(?!\z)/ ++$i % 10 ? "\t" : "\n" /eg' Data.txt
Update You've since changed your question to request fixed-width fields.
If you know the width in advance (say 10 + 2 chars between fields = 12):
perl -F'\n' -0777naE'say pack "(A12)9 A*", splice @F,0,10 while @F' Data.txt
If you don't:
perl -MList::Util=max -F'\n' -0777naE'
$w = 2 + max map length, @F;
say pack "(A$w)9 A*", splice @F,0,10 while @F;
' Data.txt
Upvotes: 5
Reputation: 974
ruby -e 'ARGF.map{|l|l.strip}.each_slice(10) {|a| puts a.join "\t"}' Data.txt
Upvotes: 2
Reputation: 4088
ikegami beat me to it. But I'll post mine anyways.
perl -pe 'tr/\n/\t/ if $. % 9 != 0'
EDIT:
Ah, even better. Thanks ikegami( for the $.
, I forgot about that one).
Upvotes: 0