Hi,
Can someone here help sorting the following data in numeric order?
INPUT:
FIRST abc(3) def(13) fgh(1) ijk(6) abc(2)
SECOND dfe(10) abc(4) hij(19) tlm(1) hij(1) hub(10) abc(1) fed(3)
OTHERS hij(10) mok(4) bub(19) hij(1) abc(2) abc(15) abc(1) hij(3)
OUTPUT:
FIRST def(13) ijk(6) abc(3) abc(2) fgh(1)
SECOND hij(19) dfe(10) hub(10) abc(4) fed(3) abc(1) hij(1) tlm(1)
OTHERS bub(19) abc(15) hij(10) mok(4) hij(3) abc(2) abc(1) hij(1)
Thanks in advance for your help!!!
That output is tricky, since it seems to be sorting in two different directions, alphabetically but reverse-numerically... commandline sort can't do that, you'd be writing your own shell-based sorting routines. Is the form of the output really that strict? What's the data for?
joeyg
February 10, 2009, 1:05pm
3
Are you sorting each line by the number in () in descending order?
The data is from CVS log and I only care about the number, not alphabetic.
All I want to do is sort numers in each row.
Thanks!
Yes. Need to sort numbers in descending order in each line.
Thank you!
Here's some code that could probably be more efficient but I think does what you want:
#!/bin/sh
while read TITLE LINE
do
ARR=( $LINE )
for ((N=0; N<${#ARR}; N++))
do
if [[ -z "${ARR[$N]}" ]]
then
break
fi
OLDIFS="${IFS}"
IFS="()"
VAL=( ${ARR[$N]} )
printf "%s %s\n" ${VAL[1]} ${VAL[0]}
IFS="${OLDIFS}"
done | sort -rn | (
echo -n $TITLE
while read I STR
do
echo -n " ${STR}(${I})"
done
echo )
done
exit 0
$ echo "FIRST abc(3) def(13) fgh(1) ijk(6) abc(2)
SECOND dfe(10) abc(4) hij(19) tlm(1) hij(1) hub(10) abc(1) fed(3)
OTHERS hij(10) mok(4) bub(19) hij(1) abc(2) abc(15) abc(1) hij(3)" | ./sorter.sh
FIRST def(13) ijk(6) abc(3) abc(2) fgh(1)
SECOND hij(19) hub(10) dfe(10) abc(4) tlm(1) hij(1) abc(1)
OTHERS bub(19) abc(15) hij(10) mok(4) abc(2) hij(1) abc(1)
$
It failed at line "ARR=( $LINE )".
syntax error at line 5: `ARR=' unexpected
need_help - what shell are you using? show the result from
echo $SHELL
Try /bin/bash instead of /bin/sh. I keep forgetting that plain sh doesn't always support "advanced" things like.. sigh.. arrays..
joeyg
February 10, 2009, 2:48pm
10
> cat file167
FIRST abc(3) def(13) fgh(1) ijk(6) abc(2)
SECOND dfe(10) abc(4) hij(19) tlm(1) hij(1) hub(10) abc(1) fed(3)
OTHERS hij(10) mok(4) bub(19) hij(1) abc(2) abc(15) abc(1) hij(3)
> cat sort167.sh
#!/usr/bin/bash
while read header data
do
# echo $header
# echo $data
revdata=`echo $data | tr " " "\n" | sort -rn +0.4 | tr "\n" " "`
echo $header $revdata
done <file167
> sort167.sh
FIRST def(13) ijk(6) abc(3) abc(2) fgh(1)
SECOND hij(19) hub(10) dfe(10) abc(4) fed(3) tlm(1) hij(1) abc(1)
OTHERS bub(19) abc(15) hij(10) mok(4) hij(3) abc(2) hij(1) abc(1)
With Perl:
perl -lane'
print join " ", shift @F, sort {
($aa) = $a =~ /(\d+)/;
($bb) = $b =~ /(\d+)/;
$bb <=> $aa
} @F
' infile
hi, i think perl should be a right and easy solution.
#!/usr/bin/perl
sub sub_sort{
my @t1=split("[(|)]",$_[0]);
my @t2=split("[(|)]",$_[1]);
if($t1[1] == $t2[1]){
return $t1[0] cmp $t2[0];
}
else{
return $t2[1] <=> $t1[1];
}
}
open FH,"<a.txt";
while(<FH>){
chomp;
my @temp=split(" ",$_);
print $temp[0]," ", join " ",sort { sub_sort($a,$b) } @temp[1..$#temp];
print "\n";
}
Nice catch summer_cherry, I did not notice that the OP wants to sort twice (first numeric, then ascii/utf8), so I need to modify the code:
perl -lane'
print join " ", shift @F, sort {
($aa) = $a =~ /(\d+)/;
($bb) = $b =~ /(\d+)/;
$bb <=> $aa || $a cmp $b
} @F
' infile