# Rearranging the column data based on alphabetical order

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

• Mar 7, 2020 at 12:36

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

• 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. Mar 7, 2020 at 16:40

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.

``````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
``````