按字典顺序排序数组。纯粹的bash

时间:2013-10-16 08:35:13

标签: arrays bash sorting

我有两个带IP的阵列。我想将它们组合成第三个数组并应用升序。

#!/bin/bash
#

dbip[0]=1.1.1.1
dbip[1]=1.1.1.2
dbip[2]=1.1.1.3
dbip[3]=1.1.1.4
dbip[4]=1.1.1.5
dbip[5]=1.1.1.10
dbip[6]=1.1.1.9

ngip[0]=1.1.1.5
ngip[1]=1.1.1.6
ngip[2]=1.1.1.7
ngip[3]=1.1.1.1
ngip[4]=1.1.1.11


#I am adding the dbip array into the final one
for (( i=0; i<${#dbip[@]}; i++ ))
do
        allip[$i]=${dbip[$i]}
done

#Remembering the no. of elements in the final array
var=${#allip[@]}
echo "$var"

#Adding the ngip array into the final one
for (( i=0; i<${#ngip[@]}; i++ ))
do
        allip[$var+$i]=${ngip[$i]}
done

#Printing the initial order of the elements in the array
echo "size= ${#allip[@]}"

for (( i=0; i<${#allip[@]}; i++ ))
do
        echo "${allip[$i]}"
done

#Sorting the array in ascending order
for (( i=0; i<${#allip[@]}; i++ ))
do
        for (( j=$i; j<${#allip[@]}; j++ ))
        do
                if [ allip[$i] \> allip[$j] ];
                then
                        aux=${allip[$i]}
                        allip[$i]=${allip[$j]}
                        allip[$j]=$aux;
                fi
        done
done

echo "###############################"

#Printing the final form of the array
for (( i=0; i<${#allip[@]}; i++ ))
do
        echo "${allip[$i]}"
done

问题是输出没有以数字或词典方式排序。

输出:

1.1.1.1
1.1.1.11
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.10
1.1.1.9
1.1.1.5
1.1.1.7
1.1.1.6

输出应该是这样的:

1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
.......
1.1.1.10
1.1.1.11

或者像这样

1.1.1.1
1.1.1.1
1.1.1.10
1.1.1.11

所以我可以稍后删除重复项。

我如何在bash中以纯编程方式执行此操作。没有管道。

请注意,IP可以来自不同的类别:10.55.72.190,10.55.70.1,10.51.72.44等。

2 个答案:

答案 0 :(得分:1)

这是“纯粹的”bash:

dbip=( [0]=1.1.1.1 [1]=1.1.1.2 [2]=1.1.1.3 [3]=1.1.1.4 [4]=1.1.1.5 [5]=1.1.1.10 [6]=1.1.1.9 )
ngip=( [0]=1.1.1.5 [1]=1.1.1.6 [2]=1.1.1.7 [3]=1.1.1.1 [4]=1.1.1.11 )
allip=( $(printf "%s\n" "${dbip[@]}" "${ngip[@]}" | sort -V) )
printf "%s\n" "${allip[@]}"
1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.5
1.1.1.6
1.1.1.7
1.1.1.9
1.1.1.10
1.1.1.11

答案 1 :(得分:0)

纯bash实现(不调用诸如sort之类的任何工具)。

这个想法:将IP转换为整数,对它们进行冒泡排序,再转换回x.x.x.x格式。

#! /bin/bash

ips=(192.0.2.235 1.1.1.1 1.1.1.11 1.1.1.1 1.1.1.2 1.1.1.3 1.1.1.4
     1.1.1.5 1.1.1.10 1.1.1.9 1.1.1.5 1.1.1.7 1.1.1.6)
# integer IPs
intips=()

echo Initial addresses:
for ((i=0; i<${#ips[@]}; ++i)); do
    echo ${ips[$i]}
done
echo

# convert ip to int
ip2int() {
    local -i intip
    local -a ip
    local IFS="."

    ip=($1)

    intip=$(( ${ip[0]}*2**24 + ${ip[1]}*2**16 + ${ip[2]}*2**8 + ${ip[3]} ))
    echo $intip
}

# convert int to ip
int2ip() {
    local -i a1 a2 a3 a4 intip=$1

    a1=$(( intip / (2**24) )); ((intip -= a1*2**24))
    a2=$(( intip / (2**16) )); ((intip -= a2*2**16))
    a3=$(( intip / (2**8) ));  ((intip -= a3*2**8))
    a4=$(($intip))
    echo "$a1.$a2.$a3.$a4"
}

# simple bubble sort (ascending) of an integer array
sortn_asc() {
    local -a array=( "$@" )
    local -i max i val1 val2

    for (( max=$(( ${#array[@]} - 1 )); max > 0; max-- )); do
        for (( i=0; i<max; i++ )); do
            val1=${array[$i]}
            val2=${array[$((i + 1))]}

            # switch if necessary
            if (( $val1 > $val2 )); then
                local tmp=$val1
                array[$i]=$val2
                array[$(($i + 1))]=$tmp
            fi
        done
    done
    echo "${array[@]}"
}

# convert ips to integers
for ((i=0; i<${#ips[@]}; ++i)); do
    intips[$i]=$(ip2int ${ips[$i]})
done

# sort
intips=( $(sortn_asc ${intips[@]}) )

# convert and echo sorted integers table
echo Sorted addresses:
for ((i=0; i<${#intips[@]}; ++i)); do
    echo $(int2ip ${intips[$i]})
done

exit 0

输出:

br@lorien:~/tmp$ ./19398658.sh 
Initial addresses:
192.0.2.235
1.1.1.1
1.1.1.11
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.10
1.1.1.9
1.1.1.5
1.1.1.7
1.1.1.6

Sorted addresses:
1.1.1.1
1.1.1.1
1.1.1.2
1.1.1.3
1.1.1.4
1.1.1.5
1.1.1.5
1.1.1.6
1.1.1.7
1.1.1.9
1.1.1.10
1.1.1.11
192.0.2.235