awk生成连续序列:

时间:2014-08-06 15:16:48

标签: unix awk

想要读取第一个字段,然后根据“& - ”和“&& - ”分隔符生成序列。

Ex: If Digits field is  210&-3 ,  need to populate 210 and 213 only.
      If Digits field is  210&&-3 , need to populate 210,211,212 and 213.

INPUT.TXT

DIGITS                    

  20
  210&-2     
  2130&&-3&-6&&-8

期望的输出:

DIGITS
  20
  210
  212
  2130
  2131
  2132
  2133
  2136
  2137
  2138

尝试了一些命令但没有实现,任何建议......

3 个答案:

答案 0 :(得分:2)

这是一个awk可执行脚本版本:

#!/usr/bin/awk -f

BEGIN {FS="[&]"}

{
    flen = length($1)
    ldigit = substr($1, flen)+0
    prefix = substr($1, 1, flen-1)+0

    if( ldigit !~ /[[:space:]]/ )
         print prefix ldigit

    doRange=0
    for(i=2;i<=NF;i++) {
        if( $i == "" ) { doRange=1; continue }
        if( !doRange ) { ldigit=-$i; print prefix ldigit }
        else {
            while( ldigit < -$i ) {
                ldigit++
                print prefix ldigit
            }
            doRange=0
        }
    }
}

以下是细分:

  • 将字段分隔符设置为&
  • 当他们是要解析的命令时,请查找prefixldigit
  • 使用print prefix ldigit打印出第一个值。这也将打印标题。 if( ldigit !~ /[[:space:]]/ )丢弃空行
  • 如果没有范围,请设置ldigit然后print prefix ldigit
  • 如果有范围,请根据需要增加ldigitprint prefix ldigit

使用较旧的gawk版本,我得到如下输出:

DIGITS
  20
  210
  212
  2130
  2131
  2132
  2133
  2136
  2137
  2138

答案 1 :(得分:1)

将GNU awk用于patsplit

gawk '{
    n = patsplit($0,patt,/[&][&]-|[&]-/,number); 
    lastnum = number[0]
    print lastnum
    if(n > 0) {
        for (i=1; i<=n; i++) {
            if (patt[i] ~ /^[&]-$/) {
                print number[0] + number[i]
                lastnum = number[0] + number[i]
            }
            if (patt[i] ~ /^[&][&]-$/) {
                for (num = lastnum + 1; num <= number[0] + number[i]; num++) {
                    print num
                }
                lastnum = number[0] + number[i]
            }
        }
    }
}' file

<强>输出

20
210
212
2130
2131
2132
2133
2136
2137
2138

答案 2 :(得分:0)

$ cat tst.awk
BEGIN{ FS="&" }
{
    for (i=1;i<=NF;i++) {
        if ($i == "") {
            i++
            $i = $1 - $i
            for (j=(prev+1);j<$i;j++) {
                print j
            }
        }
        else if ($i < 0) {
            $i = $1 - $i
        }

        print $i
        prev = $i
    }
}
$
$ awk -f tst.awk file
20
210
212
2130
2131
2132
2133
2136
2137
2138