Solved

How to sort Unix shell variable - Array

Posted on 2011-09-04
23
779 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
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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Suggested Solutions

Java performance on Solaris - Managing CPUs There are various resource controls in operating system which directly/indirectly influence the performance of application. one of the most important resource controls is "CPU".   In a multithreaded…
Why Shell Scripting? Shell scripting is a powerful method of accessing UNIX systems and it is very flexible. Shell scripts are required when we want to execute a sequence of commands in Unix flavored operating systems. “Shell” is the command line i…
Learn how to get help with Linux/Unix bash shell commands. Use help to read help documents for built in bash shell commands.: Use man to interface with the online reference manuals for shell commands.: Use man to search man pages for unknown command…
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.

813 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

10 Experts available now in Live!

Get 1:1 Help Now