Solved

How to sort Unix shell variable - Array

Posted on 2011-09-04
23
773 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
  • 9
  • 8
  • 3
  • +1
23 Comments
 
LVL 38

Expert Comment

by:wesly_chen
Comment Utility
> 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
Comment Utility
SORT -U SHOULD DO THE THING
0
 
LVL 21

Expert Comment

by:oleggold
Comment Utility
usage
sort -u $1 | \
while read arr_name
do
# ..................... whatever
done
0
 
LVL 21

Expert Comment

by:oleggold
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
@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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 

Author Comment

by:tindavid
Comment Utility
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
Comment Utility
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
Comment Utility
noop, does not work as you suggested.  

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

Expert Comment

by:wesly_chen
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
No other simple code for this sorting of array variables
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This tech tip describes how to install the Solaris Operating System from a tape backup that was created using the Solaris flash archive utility. I have used this procedure on the Solaris 8 and 9 OS, and it shoudl also work well on the Solaris 10 rel…
Using libpcap/Jpcap to capture and send packets on Solaris version (10/11) Library used: 1.      Libpcap (http://www.tcpdump.org) Version 1.2 2.      Jpcap(http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/index.html) Version 0.6 Prerequisite: 1.      GCC …
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…
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.

772 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now