2

I want to change the order of column data based on alphabetical order

Input

c,a,b
e,k,d

Output

a,b,c
d,e,k

currently, I am using the below code

awk -F"," -v OFS="," '{ 
if($1<=$2 && $2<=$3) 
{print $1,$2,$3} 
else if($1<=$2 && $3<=$2) 
{print $1,$3,$2} 
else if($2<=$1 && $1<=$3) 
{print $2,$1,$3} 
else if($2<=$1 && $3<=$1) 
{print $2,$3,$1} 
else if($3<=$2 && $2<=$1) 
{print $3,$2,$1} 
else 
{print $3,$1,$2}}' test.txt 

Could you please help me with a simpler solution to handle files having 4 or more columns

1

3 Answers 3

3

If you are okay with perl:

$ perl -F, -lane 'print join ",", sort @F' ip.txt
a,b,c
d,e,k

-F, specifies input line to be split with , as delimiter and result is available via @F array

sort @F will sort alphabetically and resulting array will be combined by join using , as separator


With GNU awk

$ awk 'BEGIN{PROCINFO["sorted_in"] = "@val_str_asc"}
       {s = ""; c=0; split($0,a,",");
        for(k in a) s = c++ ? s "," a[k] : a[k];
        print s}' ip.txt
a,b,c
d,e,k

See gawk manual: Using Predefined Array Scanning Orders for details about array ordering used above

2
  • 1
    For pre-4.0 gawks (which don't have the PROCINFO setting for array traversal) you could use asort ex. nf=asort(a); for(k=1;k<=nf;k++) s = s ? s "," a[k] : a[k]; Mar 7, 2020 at 13:12
  • Thanks both of you for your suggestions. I tried PROCINFO option and it is not sorting the data and for asort I am getting the error "function asort never defined" Could you please provide me any other solution.
    – Balaji
    Mar 7, 2020 at 16:40
1

With GNU awk for sorted_in:

$ cat tst.awk
BEGIN {
    FS=OFS=","
}
{
    sub(/\r$/,"")
    print sort($0)
}

function sort(inStr,    arr,idx,sep,outStr) {
    PROCINFO["sorted_in"] = "@val_str_asc"
    split(inStr,arr)
    for (idx in arr) {
        outStr = outStr sep arr[idx]
        sep = OFS
    }
    return outStr
}

$ awk -f tst.awk file
a,b,c
d,e,k

or with any awk but will execute much slower since it's spawning a shell to call UNIX sort for each line of input:

$ cat tst.awk
BEGIN {
    FS=OFS=","
}
{
    sub(/\r$/,"")
    print sort($0)
}

function sort(inStr,    cmd,line,sep,outStr) {
    gsub(/,/,"\n",inStr)
    cmd = "printf \047%s\n\047 \047" inStr "\047 | sort"
    while ( (cmd | getline line) > 0 ) {
        outStr = outStr sep line
        sep = OFS
    }
    close(cmd)
    return outStr
}

$ awk -f tst.awk file
a,b,c
d,e,k

The sub(/\r$/,"") is because you have DOS line endings in your posted sample input but not in your posted expected output.

0
perl -nlE 'say join ",", sort split ","'   file.txt

Explanation:

            for each line like "r,d,a":
 "r,d,a"
    ↓          split ","  it
("r","d","a")
    ↓          sort       it
("a","d","r")
    ↓          join ","   it
 "a,d,r"
               say it

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .