Sort String using awk

Hi,
I need help to sort string using awk. I don't want to use sed or perl as I want to add this functionality in my existing awk script
Basically I have a variable in AWK which is string with comma separated value. I want to sort that string before using that variable in further processing
for e.g.

echo  " PQR, ABCddf, LMNS, AAAB "|awk '{ gsub(/[[:blank:]]+/,""); SORTME=$0 ; print SORTME}'

Current output is

PQR,ABCddf,LMNS,AAAB

I want output to be sorted by words in string which are comma separated. I would like output to be displayed as

AAAB,ABCddf,LMNS,PQR

Can someone please help me to sort the output in alphabetical order

Try (using a bubble sort algorithm):

echo  " PQR, ABCddf, LMNS, AAAB "|
awk '
  {
    do {
      c="";
      for(i=1;i<NF;i++){
        if($i>$(i+1)){
          c=$i; $i=$(i+1); $(i+1)=c
        }
      }
    }
    while(c!="")
  }
  1
' FS=, OFS=,

or using GNU awk:

gawk '
  {
     n=split($0,F)
     asort(F)
     for(i=1; i<=n; i++) $i=F
  }
  1
' FS=, OFS=,

It happens to go right with the spaces that are being used, but be either careful to leave out spaces or add some code to remove the spaces...

echo  " PQR, ABCddf, LMNS, AAAB" |
awk -F, '{
    for (k=1; k<=NF; k++) x[k]=$k

    for (i=1; i<NF; i++)
        for (j=1; j<(NF+1-i); j++)
            if (x[j] > x[j+1]) {t = x[j]; x[j] = x[j+1]; x[j+1] = t}

    for (i=1; i<=NF; i++) printf("%s", (i < NF ? (i > 1 ? x FS : "\"" x FS) : x "\"" RS))
}'

With gnu awk you can also use PROCINFO["sorted_in"] like this:

echo  " PQR, ABCddf, LMNS, AAAB " | awk '
{
  PROCINFO["sorted_in"] = "@val_str_asc"
  split($0,cmds,"[ ,]*") 
  for (val in cmds) printf "%s",(k++>2?",":"") cmds[val]
  printf "\n"
}'

Excellent!!
Thanks for your help. I don't have GNU awk so all other solutions works good for me.

Last suggestion given by Chubler_XL does not give right output but rest all works good.
Thanks for your support.

---------- Post updated at 02:00 PM ---------- Previous update was at 09:52 AM ----------

Hi,

Sorry to come back again on same issue.I am stuck again with solution
I am trying to use solution provided by shamrock
How do I put that part in function so that whatever string I pass, it will sort and give me output in variable for further usage like comparison as below

snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
for sname in $snamelist
do
    BASELINE="AAAB,ABCddf,LMNS,PQR"
    echo  "$sname" | awk -v baseline="$BASELINE" 'BEGIN { FS=":" }
    { pref=$1 ; if (pref == baseline) { svcstatus = "OK" } else { svcstatus = "NOT-OK" }  ;
    printf "%-35s %-35s %-35s %-10s\n", sname, pref, baseline, svcstatus}'
done

In my actual program, pref and baseline will not be shell variable but variable in awk itself derived based on line of input. So before comparing (pref == baseline), I want to sort both so that compare can work. something like below where sortme will be function defined inline using code provided by shamrock.
looking something as below

snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
for sname in $snamelist
do
    BASELINE="AAAB,ABCddf,LMNS,PQR"
    echo  "$sname" | awk -v baseline="$BASELINE" 'BEGIN { FS=":" }
{<DEFINE SORTME FUNCTION HERE>}
    { pref=$1 ; if (sortme(pref) == sortme(baseline)) { svcstatus = "OK" } else { svcstatus = "NOT-OK" }  ;
    printf "%-35s %-35s %-35s %-10s\n", sname, pref, baseline, svcstatus}'
done

Appreciate your help.

@OP:

To sort any input string you'd have to factor out the sort part and put it into file as a standalone function and only then you can do what you are trying to get at...so put the sort function and the awk statements into a file called "sortme"...

$ cat sortme

function sortme(x,f,    j, k)
{
    for (j=1;j<f;j++)
        for (k=1;k<=f-j;k++)
            if (x[k] > x[k+1]) {
                t=x[k]
                x[k]=x[k+1]
                x[k+1]=t
            }
}

BEGIN {FS = ":" }

{
    pref=$1
    m = split(pref, srt_pref, ",")
    n = split(baseline, srt_baseline, ",")
    if (sortme(srt_pref, m) == sortme(srt_baseline, n)) svcstatus = "OK"
    else svcstatus = "NOT-OK"
    printf "%s %s %s %s\n", sname, pref, baseline, svcstatus
}

After creating the "sortme" file...change the statements inside your script...

snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"

for sname in $snamelist
do
    BASELINE="AAAB,ABCddf,LMNS,PQR"
    echo  "$sname" | awk -v baseline="$BASELINE" -f sortme
done

Bubble sort an array inside the function, which calls an array by reference, so the arrays are sorted afterwards. Then compare arrays outside the function.

snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
BASELINE="AAAB,ABCddf,LMNS,PQR"

printf "%s\n" $snamelist | 
awk -F: -v baseline="$BASELINE" '
  function arrsort(A,	n,i,c){
    n=length(A)
    do {
      c=""; 
      for(i=1;i<n;i++) {
        if(A>A[i+1]) {
          c=A; A=A[i+1]; A[i+1]=c
        }
      }
    }
    while(c!="")
  }

  BEGIN{
    split(baseline,B,/,/)
    arrsort(B)
  }

  {
    split($1,F,/,/)
    arrsort(F)
    svcstatus="OK"
    for(i in F) if(B!=F) svcstatus="NOT-OK"
    printf "%s %s %s %s\n", $0, $1, baseline, svcstatus
  }
' 

This is using a sorting method, but since the only goal is to find out if all values are present in both strings, it seems to me that this could also be done without sorting...

--
@shamrock: if (sortme(srt_pref, m) == sortme(srt_baseline, n)) is always true, no? Since the output of the sortme function is always an empty string..

Tried both solutions but did not work. Not sure if I am missing anything.
just fyi I have very limited knowledge of awk/shell scripting so something may be obvious but I may still miss it.

$ cat sortme
function sortme(x,f,    j, k)
{
    for (j=1;j<f;j++)
        for (k=1;k<=f-j;k++)
            if (x[k] > x[k+1]) {
                t=x[k]
                x[k]=x[k+1]
                x[k+1]=t
            }
}

BEGIN {FS = ":" }

{
    pref=$1
    m = split(pref, srt_pref, ",")
    n = split(baseline, srt_baseline, ",")
    if (sortme(srt_pref, m) == sortme(srt_baseline, n)) svcstatus = "OK"
    else svcstatus = "NOT-OK"
    printf "%s %s %s %s\n", sname, pref, baseline, svcstatus
}
$ snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
$ for sname in $snamelist
> do
>     BASELINE="AAAB,ABCddf,LMNS,PQR"
>     echo  "$sname" | awk -v baseline="$BASELINE" -f sortme
> done
 AAAB,ABCddf,LMNS,PQR AAAB,ABCddf,LMNS,PQR OK
 AAB,ABSSf,LMNS,DFD AAAB,ABCddf,LMNS,PQR OK
 LMNS,ABCddf,PQR,AAAB AAAB,ABCddf,LMNS,PQR OK
$ 

Output is not the expected output. 1st line should be OK, 2nd line NOT-OK and 3rd line OK

I also tried bubble sort method but its erroring out and not able to understand the error.

$ snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
$ BASELINE="AAAB,ABCddf,LMNS,PQR"
$ printf "%s\n" $snamelist | 
> awk -F: -v baseline="$BASELINE" '
>   function arrsort(A, n,i,c){
>     n=length(A)
>     do {
>       c=""; 
>       for(i=1;i<n;i++) {
>         if(A>A[i+1]) {
>           c=A; A=A[i+1]; A[i+1]=c
>         }
>       }
>     }
>     while(c!="")
>   }
> 
>   BEGIN{
>     split(baseline,B,/,/)
>     arrsort(B)
>   }
> 
>   {
>     split($1,F,/,/)
>     arrsort(F)
>     svcstatus="OK"
>     for(i in F) if(B!=F) svcstatus="NOT-OK"
>     printf "%s %s %s %s\n", $0, $1, baseline, svcstatus
>   }
> '
awk: Cannot read the value of  B. It is an array name.
 The source line number is 3.
$ 

If there is any other solution to find if both strings have same values, I am ok to use it as long as its in awk and I am be able to compare and print output as below

echo  "$sname" | awk -v baseline="$BASELINE" 'BEGIN { FS=":" }
{<DEFINE SORTME FUNCTION HERE>}
    { pref=$1 ; if (sortme(pref) == sortme(baseline)) { svcstatus = "OK" } else { svcstatus = "NOT-OK" }  ;
    printf "%-35s %-35s %-35s %-10s\n", sname, pref, baseline, svcstatus}'

Thanks for your responses.

The problem is with n=length(A) , apparently this does not work with every awk.. Try this instead:

snamelist="AAAB,ABCddf,LMNS,PQR:VALUE1 AAB,ABSSf,LMNS,DFD:VALUE2 LMNS,ABCddf,PQR,AAAB:VALUE3"
BASELINE="PQR,AAAB,ABCddf,LMNS"

printf "%s\n" $snamelist | 
awk -F: -v baseline="$BASELINE" '
  function arrsort(A,n,	i,c){
    do {
      c=""; 
      for(i=1;i<n;i++) {
        if(A>A[i+1]) {
          c=A; A=A[i+1]; A[i+1]=c
        }
      }
    }
    while(c!="")
  }
  BEGIN{
    n=split(baseline,B,/,/)
    arrsort(B,n)
  }
  {
    n=split($1,F,/,/)
    arrsort(F,n)
    svcstatus="OK"
    for(i in F) if(B!=F) svcstatus="NOT-OK"
    printf "%s %s %s %s\n", $0, $1, baseline, svcstatus
  }
' 

Otherwise what is your OS and version?

Didnt notice that the sortme function was returning an array instead of a string...here is the correct version which returns a string instead of an array ...

$ cat sortme
function sortme(x, f,   s, j, k)
{
    for (j=1;j<f;j++)
        for (k=1;k<=f-j;k++)
            if (x[k] > x[k+1]) {
                t=x[k]
                x[k]=x[k+1]
                x[k+1]=t
            }
    for (i=1; i<=f; i++) s = sprintf("%s", i<f ? x "," : x)
    return s
}

BEGIN {FS = ":" }

{
    pref=$1
    m = split(pref, srt_pref, ",")
    n = split(baseline, srt_baseline, ",")
    if ((p = sortme(srt_pref, m)) == (b = sortme(srt_baseline, n))) svcstatus = "OK"
    else svcstatus = "NOT-OK"
    printf "%s %s %s %s\n", sname, pref, baseline, svcstatus
}

Only this part needed tweaking while the other part doesnt change...

Sorry Guys, I thought I replied to this post but looks like I did not hit submit.

My issue was resolved using bubble sort suggested by "Scrutinizer"

My OS is HP-UX itanium 11.31

Thanks to all of you for your valuable and timely help.