【问题标题】:how to add/remove, number or range of numbers from a file and reorganize the range如何从文件中添加/删除数字或数字范围并重新组织范围
【发布时间】:2018-02-16 05:10:38
【问题描述】:

如何从文件中添加/删除数字或数字范围并重新组织范围

例如在文件中

$ cat test.in
cn[01-10]
cn01
cn[01,02,07-09]
cn[01-02]

要求删除 cn01 和 cn05

想要的输出

$ cat test.in
cn[02-04,06-10]
cn[02,07-09]
cn[02]

【问题讨论】:

  • 它没有被完全删除,你可以看到第一行范围是 cn[01-10] 并且在所需输出中删除 cn01 和 cn05 后,第一行修改为 cn[02-04, 06-10]
  • 一行中可能有多个范围,例如cn[02-09,04,01-04]
  • 不,一行中只出现一次范围
  • 应该如何转换cn[01-06]
  • 对于文本实用程序来说太复杂了。用你最喜欢的编程语言试试吧。

标签: linux bash awk sed grep


【解决方案1】:

以下是将列表和值范围扩展为单个值的方法:

$ cat tst.awk
function expand(exprStr,valsArr,        i,terms,term,range,val,numVals) {
    gsub(/cn|[][]/,"",exprStr)
    delete valsArr
    # exprStr = 01,02,07-09
    split(exprStr,terms,/,/)
    for (i=1; i in terms; i++) {
        # terms[1]=01, [2]=02, [3]=07-09
        term = terms[i]
        split(term,range,/-/)
        range[2] = (2 in range ? range[2] : range[1])
        for (val=range[1]; val<=range[2]; val++) {
            # range[1]=07, [2]=09
            valsArr[++numVals] = sprintf("%02d",val)
        }
    }
}
{
    print "--------", $0
    expand($0,arr)
    for (i=1; i<=length(arr); i++) {
        print i, "cn"arr[i]
    }
}

.

$ awk -f tst.awk file
-------- cn[01-10]
1 cn01
2 cn02
3 cn03
4 cn04
5 cn05
6 cn06
7 cn07
8 cn08
9 cn09
10 cn10
-------- cn01
1 cn01
-------- cn[01,02,07-09]
1 cn01
2 cn02
3 cn07
4 cn08
5 cn09
-------- cn[01-02]
1 cn01
2 cn02

现在只需从数组中删除您不想要的值,然后基本上执行相反的操作以重新组合到您的输入格式中。

【讨论】:

    【解决方案2】:

    Python 3 中的示例

    import re
    from itertools import groupby
    
    inp = """cn[01-10]
    cn01
    cn[01,02,07-09]
    cn[01-02]"""
    
    rem = {1, 5}
    
    def parse_lst(lst_str):
        for group in lst_str.split(','):
            if '-' in group:
                first, last = group.split('-')
                yield from range(int(first), int(last)+1)
            else:
                yield int(group)
    
    def format_range(range_):
        ranges = []
        for k, g in groupby(enumerate(range_), lambda x: x[0]-x[1]):
            group = [n for i, n in g]
            ranges.append((group[0], group[-1]))
    
        if not ranges:
            return
    
        print("cn[" + ','.join(
            '{:02d}'.format(first) if first == last else
            '{:02d}-{:02d}'.format(first, last) for
            first, last in ranges
        ) + ']')
    
    for line in inp.splitlines():
        lst_match = re.search(r'\[(.*)\]', line)
        if lst_match:
            range_ = parse_lst(lst_match.group(1))
        else:
            range_ = (int(line[2:]),)
    
        filtered = sorted(set(range_) - rem)
        format_range(filtered)
    

    打印

    cn[02-04,06-10]
    cn[02,07-09]
    cn[02]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-25
      • 1970-01-01
      • 2016-03-22
      • 2012-01-26
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      相关资源
      最近更新 更多