I want to print the odd-numbered and even-numbered lines from files.
I found this shell script which makes use of echo.
#!/bin/bash
# Write a shell script that, given a file name as the argument will write
# the even numbered line to a file with name evenfile and odd numbered lines
# in a text file called oddfile.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
file=$1
counter=0
eout="evenfile.$$" # even file name
oout="oddfile.$$" # odd file name
if [ $# -eq 0 ]
then
echo "$(basename $0) file"
exit 1
fi
if [ ! -f $file ]
then
echo "$file not a file"
exit 2
fi
while read line
do
# find out odd or even line number
isEvenNo=$( expr $counter % 2 )
if [ $isEvenNo -ne 0 ]
then
# even match
echo $line >> $eout
else
# odd match
echo $line >> $oout
fi
# increase counter by 1
(( counter ++ ))
done < $file
echo "Even file - $eout"
echo "Odd file - $oout"
But isn’t there a way to do it in one line?
Yes, use awk, I read.
Even-numbered lines:
awk 'NR % 2' filename
odd-numbered lines:
awk 'NR % 2 == 1' filename
But it doesn’t work for me. Both produce the same output, according to diff. When compared to the original file, they are both indeed half as long, and they both contain the odd-numbered lines. Am I doing something wrong?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I prefer to be POSIX compatible, whenever possible, so I thought I’d post this alternative method. I often use these to mangle text, before xargs pipelines.
Print Even Numbered Lines,
sed -n 'n;p'
Print Odd Numbered Lines,
sed -n 'p;n'
Although I often use awk, it’s overkill for this type of task.
Method 2
That’s easy:
sed -n 2~2p filename
will print even-numbered lines from filename
sed -n 1~2p filename
will print odd-numbered lines.
Method 3
For even numbers the code should be
awk 'NR%2==0' filename
& for odd numbers
awk 'NR%2==1' filename
Method 4
As you asked “in one line”:
awk '{print>sprintf("%sfile.%d",NR%2?"odd":"even",PROCINFO["pid"])}' filename
Note that most of the code is due to your fancy output filename choice. Otherwise the following code would be enough to put odd lines in “line-1” and even lines in “line-0”:
awk '{print>"line-"NR%2}' filename
Method 5
You can do it with a single sed invocation, no need to read the file twice:
sed '$!n w even d' infile > odd
or, if you prefer in one line:
sed -e '$!n' -e 'w even' -e d infile > odd
Note that these won’t give the expected result if a file contains only one line (the line will be written to even instead of odd as the first n isn’t executed). To avoid that, add a condition:
sed -e '$!n' -e '1!{w even' -e 'd}' infile > odd
How it works ? Well, it uses three sed commands:
n – if not on the last line print the pattern space to stdout(which is redirected to file odd), replace it with the next line (so now it’s processing an even line) and continue executing the remaining commands
w – append the pattern space to file even
d – delete current pattern space and restart the cycle – the side effect of this is that sed will never auto-print the pattern space as it never reaches the end of script
In other words, n is executed only on odd lines and w and d are executed only on even lines. sed never gets to autoprint unless, as I said, the input consists of a single line.
Method 6
Try this:
awk '{if(NR%2){print $0 > "odd.file"}else{print $0 > "even.file"}}' filename
Method 7
I’d go with perl because I like perl:
perl -pe 'BEGIN{open($e,">even_lines");open($o,">odd_lines")} $. % 2 ?select $o:select $e;'
Uses the fact that -p implicitly prints, to replicated how sed works – and we use select to choose which file handle to which it writes.
Method 8
Print even-numbered lines:
awk 'getline' file
Print odd-numbered lines:
awk '{print; getline}' file
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0