Shell 如何用逗号和连字符按范围成对打印元素数组

Shell 如何用逗号和连字符按范围成对打印元素数组

我有一个包含未知数量元素的数组,我想以这种格式打印它: item1-item2,item3-item4,item5-item6..

例如:如果 myarray 包含这些元素:0 9 11 20 22 31 33 42

我想将输出填充为:

0-9,11-20,22-31,33-42

到目前为止,我只能通过用逗号分隔元素来打印它。但我需要将其分隔在范围内:

$ printf "%s-" "${myarray[@]}"
0-9-11-20-22-31-33-42-44

感谢您的任何提示。

答案1

您可以简单地使用printf "%d-%d," "${myarray[@]}"

$ printf "%d-%d," "${myarray[@]}"
0-9,11-20,22-31,33-42,$

但是,它缺少最后的换行符并且有一个多余的逗号,因此您可以将其扩展为:

$ echo $(printf "%d-%d," "${myarray[@]}") | sed 's/,$//'
0-9,11-20,22-31,33-42

如果数组中元素的数量不为偶数,此操作将会失败(将会打印一个额外的 0):

$ myarray=(0 9 11 20 22 31 33)
$ echo $(printf "%d-%d," "${myarray[@]}") | sed 's/,$//'
0-9,11-20,22-31,33-0

您可能更喜欢使用%s只留下最后一个为空的方法:

$ echo $(printf "%s-%s," "${myarray[@]}") | sed 's/,$//'
0-9,11-20,22-31,33-

最后删除尾随的-

$ echo $(printf "%s-%s," "${myarray[@]}") | sed 's/[,-]*$//' 
0-9,11-20,22-31,33

答案2

terdon 的回答非常好。一个(可能)较慢的纯 bash 方法是

a=(0 9 11 20 22 31 33 42)
pairs=()
for ((i = 0; i < ${#a[@]}; i += 2)); do
    pairs+=( "${a[i]}-${a[i+1]}" )
done
result=$(IFS=,; echo "${pairs[*]}")
echo "$result"
0-9,11-20,22-31,33-42

或者

result=$(
    for ((i = 0; i < ${#a[@]}; i += 2)); do
        echo "${a[i]}-${a[i+1]}"
    done | paste -sd,
)

或者(我无法抗拒这种事)

sep="-"
for elem in "${a[@]}"; do
    printf "%s%s" "$elem" $sep
    [[ $sep == "-" ]] && sep="," || sep="-"
done | sed 's/.$//'

相关内容