首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将逗号分隔的数字列表转换为连字符列表或范围

将逗号分隔的数字列表转换为连字符列表或范围
EN

Unix & Linux用户
提问于 2020-01-15 22:03:19
回答 6查看 1K关注 0票数 2

我有一个逗号分隔的数字字符串,如下所示:

代码语言:javascript
运行
复制
1,2,3,5,6,7,8,9,12,14

我正在寻找在bash脚本中使用的命令,该命令可以将相邻的数字组合成范围/连字符条目,如下所示:

代码语言:javascript
运行
复制
1-3,5-9,12,14

初始字符串保证按升序排序。

EN

回答 6

Unix & Linux用户

回答已采纳

发布于 2020-01-16 18:11:25

最后,我使用了一个数组来携带已识别的范围,得到了以下BASH函数。输入字符串是函数的第一个参数,结果通过第二个参数传回:

代码语言:javascript
运行
复制
function compact_range {
  arr=()
  start=""
  for cpu in ${1//,/ }; do
    # Start a new range definition if necessary
    [ -z "$start" ] && start=$cpu && range=$cpu && last=$cpu && continue
    prev=$(( $cpu - 1 ))
    # If the current CPU is not adjacent to the last CPU, start a new range
    [ "$prev" -ne "$last" ] && arr+=($range) && start=$cpu && range=$cpu && last=$cpu && continue
    # Current CPU is adjacent to an existing range, expand the current range
    range="${start}-${cpu}" && last=$cpu
  done
  # Append the last range to the array of ranges
  arr+=($range)
  # Return a comma delimited list of ranges
  eval $2=$(IFS=,;printf "%s" "${arr[*]}")
}

谢谢大家的建议。

票数 0
EN

Unix & Linux用户

发布于 2020-01-16 00:06:39

使用perl:

代码语言:javascript
运行
复制
perl -pe 's/\b(\d+)(?{$q=$1+1})(?:,(??{$q})\b(?{$p=$q++})){2,}/$1-$p/g'

这是通过(?{...})(??{...})表达式使用嵌入perl代码的正则表达式;第一个表达式只是计算嵌入式代码,而第二个表达式使用它返回的值作为模式。有关完整的描述,请参见perlre(1)

如果你也想要两个数字的范围,用{2,}量词替换为+ (例如。1,2,7 -> 1-2,7)。

票数 1
EN

Unix & Linux用户

发布于 2020-01-15 22:51:53

下面是一个简短的awk脚本,它遍历以逗号分隔的排序整数列表,并在此过程中填充两个数组ab

a数组将包含每个单调递增整数范围的起始整数,而b将包含相应的结束整数。代码中的变量n保存已找到的范围的数量。

代码语言:javascript
运行
复制
BEGIN {
    OFS = FS = ","
}

{
    n = 0

    a[++n] = $1
    for (i = 1; i < NF; ++i)
        if ($i != $(i+1) - 1) {
            b[n] = $i
            a[++n] = $(i+1)
        }
    b[n] = $NF

    $0 = ""

    for (i = 1; i <= n; ++i)
        if (a[i] == b[i])
            $i = a[i]
        else
            $i = sprintf("%d-%d", a[i], b[i])

    print
}

该输出是通过迭代n找到的不同范围并构造一个记录来创建的,其中每个字段要么是单个整数(对于长度为1的范围),要么是表示范围的开始和结束的字符串。

对所提供的数据进行测试,从文件中读取数据:

代码语言:javascript
运行
复制
$ awk -f script.awk file
1-3,5-9,12,14

显然,您可以从标准输入中输入一个字符串,如下所示:

代码语言:javascript
运行
复制
$ awk -f script.awk <<<"1,2,3,5,9,10,11,12,13"
1-3,5,9-13
票数 0
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/562335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档