How can I take sort bash arguments alphabetically?
$ ./script.sh bbb aaa ddd ccc
and put it into an array such that I now have an array {aaa, bbb, ccc, ddd}
How can I take sort bash arguments alphabetically?
$ ./script.sh bbb aaa ddd ccc
and put it into an array such that I now have an array {aaa, bbb, ccc, ddd}
You can do:
A=( $(sort <(printf "%s\n" "$@")) )
printf "%s\n" "${A[@]}"
aaa
bbb
ccc
ddd
It is using steps:
arguments list i.e."$@"`I hope following 2 lines will help.
sorted=$(printf '%s\n' "$@"|sort)
echo $sorted
This will give you a sorted cmdline args.I wonder though why its needed :)
But anyway it will sort your cmdlines
Removed whatever was not required.
Here's an invocation that breaks all the other solutions proposed here:
./script.sh "foo bar" "*" "" $'baz\ncow'
Here's a piece of code that works correctly:
array=()
(( $# )) && while IFS= read -r -d '' var
do
array+=("$var")
done < <(printf "%s\0" "$@" | sort -z)
As there seem not appreciate my effort to reducing forks, there is a better solution than using IFS for parsing and setting a variable
As suggested by @rici in a comment on another post, I add the -t argument to mapfile:
mapfile -t args < <(sort < <(printf "%s\n" "$@"))
This work with white space too.
Sample:
#!/bin/bash
mapfile args < <(sort < <(printf "%s\n" "$@"))
mapfile -t args < <(sort < <(printf "%s\n" "$@"))
declare -p args
for (( i=0 ; i<${#args[@]} ;i++));do
printf "%3d: %s\n" $i "${args[i]%$'\n'}"
printf "%3d: %s\n" $i "${args[i]}"
done
run sample:
/tmp/script ccc "a a" aaa ddd aa AA z aab
declare -a args='([0]="aa
" [1]="a a
" [2]="AA
" [3]="aaa
" [4]="aab
" [5]="ccc
" [6]="ddd
" [7]="z
")'
0: aa
1: a a
2: AA
3: aaa
4: aab
5: ccc
6: ddd
7: z
Nota: Of course, this is not the better, robust way of doing sort, but in many cases, this could efficiently be used.
As (at least) one guy seem prefer a to be sorted before aa, this is edited to replace z by 0.
This sample is limited to 1st 6 chars but you could replace 6 by bigger number but add same number of z.
#!/bin/bash
sep='§'
for i;do
a=${i//[^a-zA-Z0-9]/0}000000
args[36#${a:0:6}]+=${args[36#${a:0:6}]+$sep}${i}
done
IFS=$sep args=(${args[*]})
printf "%s\n" ${args[@]}
declare -p args
For case sensitivity, you could replace 36# by 64#:
#!/bin/bash
sep=§
base=64
chars=8
fillc=0
usage() {
cat <<eousage
Usage: $0 [-ai] [-p precision] [-s inner separator]
-a for sorting \`\`empty'' After (\`\`aa'' after \`\`aaa'')
-i for case Insensitive
-p NUM tell the number of characters to compare (default: $chars)
-s SEP let you precise inner separator, (default \`\`$sep'')
eousage
}
while getopts "iap:s:" opt;do case $opt in
a ) fillc=z ;;
i ) base=36 ;;
p ) chars=$OPTARG ;;
s ) sep=$OPTARG ;;
* ) usage ; exit 1 ;;
esac ; done ;
shift $[OPTIND-1]
printf -v cfill "%${chars}s"
cfill=${cfill// /$fillc}
for i;do
a=${i//[^a-zA-Z0-9]/$fillc}$cfill
idx=$[$base#${a:0:$chars}]
args[$idx]+=${args[$idx]+$sep}${i}
done
declare -p args
IFS=$sep args=(${args[*]})
declare -p args
for (( i=0 ; i++<${#args[@]} ;b));do
printf "%3d: %s\n" $i ${args[i-1]}
done
Run cases:
/tmp/script ccc aaa ddd aa AA z aab
declare -a args='([44667659878400]="aa" [44678397296640]="aaa"
[44679471038464]="aab" [53614076755968]="ccc" [58081916485632]="ddd"
[153931627888640]="z" [160803575562240]="AA")'
declare -a args='([0]="aa" [1]="aaa" [2]="aab" [3]="ccc" [4]="ddd"
[5]="z" [6]="AA")'
1: aa
2: aaa
3: aab
4: ccc
5: ddd
6: z
7: AA
Case insensitive:
/tmp/script -i ccc aaa ddd aa AA z aab
declare -a args='([805409464320]="aa§AA" [806014126080]="aaa"
[806074592256]="aab" [967216951296]="ccc" [1047818363904]="ddd"
[2742745743360]="z")'
declare -a args='([0]="aa" [1]="AA" [2]="aaa" [3]="aab" [4]="ccc"
[5]="ddd" [6]="z")'
1: aa
2: AA
3: aaa
4: aab
5: ccc
6: ddd
Empty sorted after:
/tmp/script -ia ccc aaa ddd aa AA z aab
declare -a args='([806074592255]="aaa" [806135058431]="aab"
[807586246655]="aa§AA" [967277417471]="ccc" [1047878830079]="ddd"
[2821109907455]="z")'
declare -a args='([0]="aaa" [1]="aab" [2]="aa" [3]="AA" [4]="ccc"
[5]="ddd" [6]="z")'
1: aaa
2: aab
3: aa
4: AA
5: ccc
6: ddd
7: z
precision: 1 chars:
/tmp/script -iap1 ccc aaa ddd aa AA z aab
declare -a args='([10]="aaa§aa§AA§aab" [12]="ccc" [13]="ddd" [35]="z")'
declare -a args='([0]="aaa" [1]="aa" [2]="AA" [3]="aab" [4]="ccc"
[5]="ddd" [6]="z")'
1: aaa
2: aa
3: AA
4: aab
5: ccc
6: ddd
7: z
and precision: 10 chars:
/tmp/script -p 10 ccc aaa ddd aa AA z aab
declare -a args='([182958734861926400]="aa" [183002715327037440]="aaa"
[183007113373548544]="aab" [219603258392444928]="ccc"
[237903529925148672]="ddd" [630503947831869440]="z"
[658651445502935040]="AA")'
declare -a args='([0]="aa" [1]="aaa" [2]="aab" [3]="ccc" [4]="ddd"
[5]="z" [6]="AA")'
1: aa
2: aaa
3: aab
4: ccc
5: ddd
6: z
7: AA
Whitespaces and other chars:
/tmp/script -is @ ccc "a a" aaa ddd 'a*a' 'a§a' aa AA z aab
declare -a args='([784246302720]="a a@a*a@a§a" [805409464320]="aa@AA"
[806014126080]="aaa" [806074592256]="aab" [967216951296]="ccc"
[1047818363904]="ddd" [2742745743360]="z")'
declare -a args='([0]="a a" [1]="a*a" [2]="a§a" [3]="aa" [4]="AA"
[5]="aaa" [6]="aab" [7]="ccc" [8]="ddd" [9]="z")'
1: a a
2: a*a
3: a§a
4: aa
5: AA
6: aaa
7: aab
8: ccc
9: ddd
10: z