我该如何按字母顺序排列bash参数?
$ ./script.sh bbb aaa ddd ccc
将其放入一个数组中,使我现在有一个数组{aaa,bbb,ccc,ddd}
$ ./script.sh bbb aaa ddd ccc
将其放入一个数组中,使我现在有一个数组{aaa,bbb,ccc,ddd}
您可以进行以下操作:
A=( $(sort <(printf "%s\n" "$@")) )
printf "%s\n" "${A[@]}"
aaa
bbb
ccc
ddd
使用步骤如下:
declare -a A=($(sort <(printf "%s\n" "$@")))
呢? - F. Hauri - Give Up GitHubsortargs() { mapfile -t $1 < <(printf "%s\n" "${@:2}"|sort); }; sortargs A "foo bar" "*" "" $'baz\tcow'; printf "%s\n" "${A[@]}"
. 当然,仍然无法处理换行符。 - rici我希望以下两行内容能够帮到您。
sorted=$(printf '%s\n' "$@"|sort)
echo $sorted
这会给你一个已排序的命令行参数。不过我不知道为什么需要它 :)
但无论如何,它将对您的命令行进行排序
删除了不必要的内容。
由于似乎没有人欣赏我减少分支的努力,所以有一个比使用IFS
解析和设置变量更好的解决方案。
正如@rici在另一篇帖子的评论中建议的那样,我添加了-t
参数到mapfile
中:
mapfile -t args < <(sort < <(printf "%s\n" "$@"))
这也适用于空格。
示例:
#!/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
运行示例:
/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
注意:当然,这不是更好、更健壮的排序方式,但在许多情况下,这可能会有效地使用。
由于(至少)一个人似乎更喜欢将a
排在aa
之前,因此现在将z
替换为0
。
此示例仅限于1st 6个字符,但您可以将6替换为更大的数字,但要添加相同数量的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
为了区分大小写,您可以将36#
替换为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
运行测试用例:
/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
不区分大小写:
/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
排序后为空:
/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
精度:1个字符:
/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
和精度:10个字符:
/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
空格和其他字符:
/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
abc
排序在a
之前并且删除空元素。冒泡排序不是更简单和更准确吗? - that other guy这里有一个调用,可以打破所有其他在此处提出的解决方案:
./script.sh "foo bar" "*" "" $'baz\ncow'
array=()
(( $# )) && while IFS= read -r -d '' var
do
array+=("$var")
done < <(printf "%s\0" "$@" | sort -z)
$@
中拥有它们。 - PradyJord