Solved

How to sort Unix shell variable - Array

Posted on 2011-09-04
23
801 Views
Last Modified: 2012-05-12
I have the array variables like below:

arr_name[1]='ADAM'      arr_id[1]=9999
arr_name[2]='XEROX'    arr_id[2]=1234
arr_name[3]='PENNY'    arr_id[3]=8767

I want sort the array variable by

1) arr_id[]  
2) arr_name[]

if sort by arr_name, th resulting array variable will be:

arr_name[1]='ADAM'      arr_id[1]=9999
arr_name[2]='PENNY'     arr_id[2]=8767
arr_name[3]='XEROX'     arr_id[3]=1234

if sort by arr_id, the result should be

arr_name[1]='XEROX'   arr_id[1]=1234
arr_name[2]='PENNY'    arr_id[2]=8767
arr_name[3]='ADAM'     arr_id[3]='9999

Please also provide the solution of Descending order

Notice:  I want a simple command to do the sorting NOT a solution contain a loop of compare this and that
0
Comment
Question by:tindavid
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
  • 3
  • +1
23 Comments
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482290
> I want a simple command to do the sorting NOT a solution contain a loop of compare this and that
The short answer is NO.  You have two arrays, not just one array. So there is no way to sort two arrays with associated items without loop.
Here is the URL
http://ubuntuforums.org/archive/index.php/t-1689348.html

#!/bin/bash

arr_name=( ADARM XEROX PENNY )
arr_id=( 9999   1124   8767 )

echo BEFORE:
echo ${arr_name[@]}
echo ${arr_id[@]}

tmp=$( for (( i=0; i<${#arr_name[@]}; i++ ))
do
echo ${arr_name[i]} ${arr_id[i]}
done | sort -nk2)  # ascend by arr_name  : sort
                   # descend by arr_name : sort -r
                   # ascend by arr_id    : sort -nk2
                   # descend by arr_id   : sort -nrk2

arr_name=( $( echo "$tmp" | awk '{print $1 }' ) )
arr_id=( $( echo "$tmp" | awk '{print $2 }' ) )

echo AFTER:
echo ${arr_name[@]}
echo ${arr_id[@]}

Open in new window

0
 
LVL 21

Expert Comment

by:oleggold
ID: 36482293
SORT -U SHOULD DO THE THING
0
 
LVL 21

Expert Comment

by:oleggold
ID: 36482297
usage
sort -u $1 | \
while read arr_name
do
# ..................... whatever
done
0
What Is Transaction Monitoring and who needs it?

Synthetic Transaction Monitoring that you need for the day to day, which ensures your business website keeps running optimally, and that there is no downtime to impact your customer experience.

 
LVL 21

Expert Comment

by:oleggold
ID: 36482303
they also use sort-u here:
http://programming.itags.org/unix-linux-programming/96608/
You can also use perl or awk but this ultimately will be NOT "simple command to do the sorting "
0
 
LVL 48

Expert Comment

by:Tintin
ID: 36482311
echo "${arr_name[@]}"| tr ' ' '\n' | sort | tr '\n' ' '

Open in new window


echo "${arr_id[@]}"| tr ' ' '\n' | sort -rn | tr '\n' ' '

Open in new window

0
 

Author Comment

by:tindavid
ID: 36482352
Hi Wesly,

After adding your code to my test program, got an error:


$ sh test.sh 5
Before sorting ...
 54 myname01
 53 myname02
 52 myname03
 51 myname04
 50 myname05

test.sh[39]: Syntax error at line 1 : `((' is not expected.



Please help

test.sh
0
 

Author Comment

by:tindavid
ID: 36482384
Hi All,

I want to sort array of variables NOT just single array.

arr_id[]  arr_name[]  arr_address[]  etc
0
 
LVL 48

Expert Comment

by:Tintin
ID: 36482391
If your data structure is like that, then I'd suggest that you either need to look at another type of data structure or programming language.

Can you go back a few steps and describe what you are trying to achieve with your data?
0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482393
array index start from 0, not 1, please change your test.sh to "i=0" and  "j=0"

#!/bin/ksh

build_array()
{
  temp_val=`expr ${arridx} + 50`
  i=0
  while [ $i -le $arridx ]
  do
     arr_id[$i]=`expr ${temp_val} - $i`
     arr_name[$i]="myname0${i}"
     i=`expr $i + 1`
  done
  idx=${#arr_id[*]}
}

print_array()
{
  j=0
  while [ $j -le ${1} ]
  do
    echo " ${arr_id[$j]} ${arr_name[$j]}"
    j=`expr $j + 1`
  done
}

if [ $# -ne 1 ] && [ ${1} -ge 2 ]; then
   echo "Usage $0 number_of_array"
   exit
fi

arridx=${1}
build_array
echo "Before sorting ..."
print_array $arridx

tmp=$( for (( i=0; i<${#arr_name[@]}; i++ ))
do
echo ${arr_name[i]} ${arr_id[i]}
done | sort -nk2)  # ascend by arr_name  : sort
                   # descend by arr_name : sort -r
                   # ascend by arr_id    : sort -nk2
                   # descend by arr_id   : sort -nrk2

arr_name=( $( echo "$tmp" | awk '{print $1 }' ) )
arr_id=( $( echo "$tmp" | awk '{print $2 }' ) )

echo "After sort"
print_array $arridx

Open in new window

0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482401
As my comment in the code, for ascending or descending, just change the line 39
done | sort -nk2)  # ascend by arr_id
to
done | sort )     # ascend by arr_name
or
done | sort -r ) # descend by arr_name
or
done | sort -nrk2)   # descend by arr_id
0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482405
@Tintin
What tindavid want is more like hash in perl or bash4.

@tindavid
Perl hash is more easier.
Here is the sample.

#!/usr/bin/perl -w

# DEFINE A HASH
%hash = ( "ADARM" => 9999,
          "XEROX" => 1234 ,
          "PENNY" => 8767 );
# Sort by keys
print "Sort by keys:\n";
foreach $key (sort keys %hash) {
     print "$key $hash{$key}\n";
}
# Sort by values
print "Sort by values:\n";
foreach $value (sort {$hash{$a} cmp $hash{$b} } keys %hash) {
     print "$value $hash{$value}\n";
}

Open in new window

0
 

Author Comment

by:tindavid
ID: 36482498
I prefer a shell solution.

Wesly, still error is executing line of

tmp=$(........ )
do
   .....
done

I am doing this in HP-UX are you ?
0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482511
Sorry, change the first line from
#!/bin/ksh
to
#!/bin/bash

Make sure you have bash shell on HP-UX
0
 

Author Comment

by:tindavid
ID: 36482619
noop, does not work as you suggested.  

Can you write a korn shell for this ?
0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482748
I don't have HP-UX. Tested with the ksh on Linux and it works for me.
#!/bin/ksh

build_array()
{
  temp_val=`expr ${arridx} + 50`
  i=0
  while [ $i -le $arridx ]
  do
     arr_id[$i]=`expr ${temp_val} - $i`
     arr_name[$i]="myname0${i}"
     i=`expr $i + 1`
  done
  idx=${#arr_id[*]}
}

print_array()
{
  j=0
  while [ $j -le ${1} ]
  do
    echo " ${arr_id[$j]} ${arr_name[$j]}"
    j=`expr $j + 1`
  done
}

if [ $# -ne 1 ] && [ ${1} -ge 2 ]; then
   echo "Usage $0 number_of_array"
   exit
fi

arridx=${1}
build_array
echo "Before sorting ..."
print_array $arridx

cat /dev/null > /tmp/2d_array
c=0
while [ $c -lt ${#arr_name[@]} ]
do
    echo "${arr_id[c]} ${arr_name[c]}" >> /tmp/2d_array
    c=`expr $c + 1`
done

arr_id=(`[b]sort[/b] /tmp/2d_array | awk '{print $1 }' | sed ':a;N;$!ba;s/\n/ /g'`)
arr_name=(`[b]sort[/b] /tmp/2d_array | awk '{print $2 }' | sed ':a;N;$!ba;s/\n/ /g'`)

rm -f /tmp/2d_array

echo "After sort"
print_array $arridx

Open in new window

0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36482755
line 44 and 45 should be
arr_id=(`sort /tmp/2d_array | awk '{print $1 }' | sed ':a;N;$!ba;s/\n/ /g'`)
arr_name=(`sort /tmp/2d_array | awk '{print $2 }' | sed ':a;N;$!ba;s/\n/ /g'`)
0
 
LVL 48

Expert Comment

by:Tintin
ID: 36482819
In 99% of cases with shell scripts, arrays aren't needed as there is generally a much easier and more efficient way of handling the processing.

Please explain how you want to manipulate your data.
0
 

Author Comment

by:tindavid
ID: 36483227
echo "After sort"
print_array $arridx
hp800l[montr92][/home/dba/oracle/dtin] >ksh test4.sh 5
Before sorting ...
 55 myname00
 54 myname01
 53 myname02
 52 myname03
 51 myname04
 50 myname05
test4.sh[38]: syntax error at line 44 : `(' unexpected

still error
0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36485150
It seems like ksh on HP-UX doesn't support array=( item1  item2 ).
Modified the whole script as
-----------
#!/bin/ksh

build_array()
{
  temp_val=`expr ${arridx} + 50`
  i=0
  while [ $i -le $arridx ]
  do
     arr_id[$i]=`expr ${temp_val} - $i`
     arr_name[$i]="myname0${i}"
     echo "${arr_id[$i]} ${arr_name[$i]}" >> /tmp/2d_array
     i=`expr $i + 1`
  done
  idx=${#arr_id[*]}
}

sort_array()
{
  c=0
  sort /tmp/2d_array | while read id name    # Change sort to "sort -r", "sort -k2", or "sort -kr2"
  do
     arr_id[$c]=$id
     arr_name[$c]=$name
     c=`expr $c + 1`
  done
}


print_array()
{
  j=0
  while [ $j -le ${1} ]
  do
    echo "${arr_id[$j]} ${arr_name[$j]}"
    j=`expr $j + 1`
  done
}

if [ $# -ne 1 ] && [ ${1} -ge 2 ]; then
   echo "Usage $0 number_of_array"
   exit
fi

cat /dev/null > /tmp/2d_array
arridx=${1}
build_array
echo "Before sorting ..."
print_array $arridx
sort_array

rm -f /tmp/2d_array

echo "After sort"
print_array $arridx

#!/bin/ksh

build_array()
{
  temp_val=`expr ${arridx} + 50`
  i=0
  while [ $i -le $arridx ]
  do
     arr_id[$i]=`expr ${temp_val} - $i`
     arr_name[$i]="myname0${i}"
     echo "${arr_id[$i]} ${arr_name[$i]}" >> /tmp/2d_array
     i=`expr $i + 1`
  done
  idx=${#arr_id[*]}
}

sort_array()
{
  c=0
  sort /tmp/2d_array | while read id name
  do
     arr_id[$c]=$id
     arr_name[$c]=$name
     c=`expr $c + 1`
  done
}

print_array()
{
  j=0
  while [ $j -le ${1} ]
  do
    echo "${arr_id[$j]} ${arr_name[$j]}"
    j=`expr $j + 1`
  done
}

if [ $# -ne 1 ] && [ ${1} -ge 2 ]; then
   echo "Usage $0 number_of_array"
   exit
fi

cat /dev/null > /tmp/2d_array
arridx=${1}
build_array
echo "Before sorting ..."
print_array $arridx
sort_array

rm -f /tmp/2d_array

echo "After sort"
print_array $arridx

Open in new window

0
 
LVL 38

Expert Comment

by:wesly_chen
ID: 36485197
You can remove line 11 and add
---------
join_arrays_to_file()
{
  c=0
  while [ $c -lt ${#arr_name[@]} ]
  do
    echo "${arr_id[c]} ${arr_name[c]}" >> /tmp/2d_array
    c=`expr $c + 1`
  done
}
#!/bin/ksh

build_array()
{
  temp_val=`expr ${arridx} + 50`
  i=0
  while [ $i -le $arridx ]
  do
     arr_id[$i]=`expr ${temp_val} - $i`
     arr_name[$i]="myname0${i}"
     i=`expr $i + 1`
  done
  idx=${#arr_id[*]}
}

join_arrays_to_file()
{
  c=0
  while [ $c -lt ${#arr_name[@]} ]
  do
    echo "${arr_id[c]} ${arr_name[c]}" >> /tmp/2d_array
    c=`expr $c + 1`
  done
}

sort_array()
{
  c=0
  sort /tmp/2d_array | while read id name # Change sort to "sort -r", "sort -k2", or "sort -kr2"
  do
     arr_id[$c]=$id
     arr_name[$c]=$name
     c=`expr $c + 1`
  done
}

print_array()
{
  j=0
  while [ $j -le ${1} ]
  do
    echo "${arr_id[$j]} ${arr_name[$j]}"
    j=`expr $j + 1`
  done
}

if [ $# -ne 1 ] && [ ${1} -ge 2 ]; then
   echo "Usage $0 number_of_array"
   exit
fi

cat /dev/null > /tmp/2d_array
arridx=${1}
build_array
echo "Before sorting ..."
print_array $arridx
join_arrays_to_file
sort_array

rm -f /tmp/2d_array

echo "After sorting ..."
print_array $arridx

Open in new window

0
 

Accepted Solution

by:
tindavid earned 0 total points
ID: 36533697
Dear All,

Seems like there is not simple command to perform sorting of array variables in Korn Shell. If I have to use temp file, I have already had my complex solution to do that , instead I have a solution that will not use temp file but still able to sort the array variable using comparsion method.


sortarray.sh
0
 

Author Comment

by:tindavid
ID: 36533701
if there is no simple soltion to sort array variables, then I have to call for deletion of this question.  Thank you for your help.
0
 

Author Closing Comment

by:tindavid
ID: 36555867
No other simple code for this sorting of array variables
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When you do backups in the Solaris Operating System, the file system must be inactive. Otherwise, the output may be inconsistent. A file system is inactive when it's unmounted or it's write-locked by the operating system. Although the fssnap utility…
Background Still having to process all these year-end "csv" files received from all these sources (including Government entities), sometimes we have the need to examine the contents due to data error, etc... As a "Unix" shop, our only readily …
Learn how to navigate the file tree with the shell. Use pwd to print the current working directory: Use ls to list a directory's contents: Use cd to change to a new directory: Use wildcards instead of typing out long directory names: Use ../ to move…
In a previous video, we went over how to export a DynamoDB table into Amazon S3.  In this video, we show how to load the export from S3 into a DynamoDB table.

717 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question