awk {if}条件中的数字表达式

时间:2016-03-01 19:13:39

标签: regex linux bash shell awk

AWK编程很新。我有一个文件1,条目为:

15>000000513609200>000000513609200>B>I>0011>>238/PLMN/000100>File Ef141109.txt>0100-75607-16156-14 09-11-2014
15>000000513609200>000000513609200>B>I>0011>Danske Politi>238/PLMN/000200>>0100-75607-16156-14 09-11-2014
15>000050354428060>000050354428060>B>I>0011>Danske Politi>238/PLMN/000200>>4100-75607-01302-14 31-10-2014

我想写一个awk脚本,如果从第3个字段减去的第2个字段是0,那么它打印字段2.否则,如果(差异> 0),则打印所有中间数字,从1开始递增第二场以第三场结束。没有第三场小于第二场的情况。所以忽略了那个条件。

我做的事情是:

 awk 'NR > 2 { print p } { p = $0 }' file1 | awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'

((有人告诉我awk在语法方面接近C))

但是从输出中我看起来,String到数字或数字到字符串的转换并不是在正确的时间在正确的位置发生的。 AWK不应该自动照顾它吗?

我得到的输出:

513609200
513609201
513609200

这并不像预期的那样安静。一个明显的问题是它忽略了前面的0。

请帮我修改AWK脚本以获得所需的结果。

注:

awk 'NR > 2 { print p } { p = $0 }' file1只是删除原始文件1中的第一个和最后一个条目。所以需要修复的部分是:

awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'

3 个答案:

答案 0 :(得分:2)

在awk中,将$视为运算符以检索指定字段编号($ 0为a特例)

  • $1是字段1
  • 的值
  • $NFNF变量
  • 中给出的字段的值

因此,$($3 - $2)会尝试获取表达式($ 3 - $ 2)给出的字段数的值。

您需要更少$个标志

awk -F">" '{
    if ($3 == $2) 
        print $2
    else {
        v=$2
        while (v < $3) 
            print v++
    }
}'

答案 1 :(得分:1)

通常,这会起作用,但是你的数字超出awk整数范围,所以你需要另一个解决方案来处理它们。我发布这个以启动其他解决方案并更好地说明您的规格。

$ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file

请注意,这将跳过您说不可能发生的行

一个小规模的例子

$ cat file_0
x>1000>1000>etc
x>2000>2003>etc
x>3000>2999>etc

$ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file_0
1000
2000
2001
2002
2003

显然,gawk的较新版本对任意精度整数都有--bignum个选项,如果您有兼容的版本可以解决您的问题,但我无权验证。

答案 2 :(得分:0)

对于那些无法随时访问gawk并且支持bigint的人,如果某种&#34;大整数&#34;可能更容易考虑其他选项。需要支持。由于ruby具有类似awk的操作模式, 我们在这里考虑红宝石。

要开始使用,只需记住四件事:

  1. 使用-n和-a选项调用ruby(-n用于类似awk的循环; -a用于自动将行解析为字段($ F [i]));
  2. awk&#39; s $ n变为$ F [n-1];
  3. 需要将数字字符串显式转换为整数;
  4. 要指定要在命令行上执行的行,请使用&#39; -e TEXT&#39;选项。
  5. 因此直接翻译:

    awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file
    

    将是:

    ruby -an -F'>' -e '($F[1].to_i .. $F[2].to_i).each {|i| puts i }' file
    

    为了防止空行,下面的脚本会稍好一些:

    ($F[1].to_i .. $F[2].to_i).each {|i| puts i } if $F.length > 2
    

    这可以像上面那样调用,或者如果脚本使用咒语在文件中(比如script.rb):

    ruby -an -F'>' script.rb file
    

    给定OP输入数据,输出为:

    513609200
    513609200
    50354428060
    

    左边填充可以通过多种方式完成 - 例如参见this SO page