【问题标题】:How to check a condition and then print specific fields in lines before the line with the condition using awk?如何检查条件,然后使用 awk 在具有条件的行之前的行中打印特定字段?
【发布时间】:2015-07-22 22:19:34
【问题描述】:

我有一个带有以下输出的文件:

58.752391 0.000  1 1  6.152565 2.757839 14.558406 0.000000 2.156979  0.000000 0.000000  0 0 0  1
16.089417316313 0.000000000000 6.171292860915 2.757949885550  -150168 0
6.953218e-310 0.000000e+00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0 0 0 0 0.000000   0.000000 0.000000  0
0.000000 0.000000 0 0 0 0 0.000000   0.000000 0.000000  0
-1.000000 -1.000000
0 

14034.172996 0.000  13 13  1.107936 1.107936 -1.000000 -1.000000 -1.000000  23.670258 34.172995  0 0 0  0
3085.963203076240 0.667625281751 10.905159250868 8.915904022910  -150168 639
6.953218e-310 0.000000e+00 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
3.120454 8.844320 8 1 127.895 0 23.670258   1.107936 0.000000  0
1.107936 8.390152 13 5 1e+50 0 34.172995   1.107936 0.000000  0
-1.000000 -1.000000
3 CE1(5-1;8-1) SN1 SN2 

等等……

我想检查第 6 行(然后每 8 行)中的两个数字是否不同于 -1.000000。如果是这样,根据哪个(第一个、第二个或两者)不同,我想产生以下输出:

1) 第一个数字不同于-1.000000:

这个不同的数字,这个数字之前的 4 行 - 第三列(在本例中,如果数字不同于 -1.000000,则为 6.171292860915),此数字之前的 2 行 - 第 8 列(在本例中为 0.000000),同一行 -第 7 列,此数字之后的行

2) 第二个数字不同于-1.000000:

这个不同的数字,这个数字之前的 4 行 - 第四列,这个数字之前的 1 行 - 第 8 列,同一行 - 第 7 列,这个数字之后的行

3) 第一个和第二个数字不是-1.000000:

1) 的输出 2) 的输出

我知道如何使用 sed 在我的示例中提取 -1.000000 所在的这些行。现在我想我应该在我的 sed 命令中包含一些 awk 的 ifs 来检查该行是否包含 -1.000000 或其他数字,然后打印我需要的内容。但是,我不知道如何引用 sed 正在检查的行之前的行。我将不胜感激任何帮助或线索。谢谢!

【问题讨论】:

  • 也写输出。你不能通过 awk 做到这一点。 awk 不能回溯文件行。我们必须编写shell脚本
  • @ShravanYadav 我不知道我不能用 awk 回溯。谢谢!你能帮我处理这个 shell 脚本吗?
  • 分享您需要的确切输出?不是输出描述
  • 例如-1.000000, 6.171292860915, 0.000000, 0.000000, 0 每个数字用逗号分隔。每个输出都在一个新行中。

标签: linux shell awk sed


【解决方案1】:

Perl 的救援:

#!/usr/bin/perl
use warnings;
use strict;

# Read in "paragraph mode".
$/ = q();

# Auto add newlines.
$\ = "\n";

while (<>) {
    my @lines = map [ split ], split /\n/;  # Create an array of arrays.
    if (-1 != $lines[5][0]) {
        print join ' ', $lines[5][0], $lines[1][2], $lines[3][7],
                        $lines[3][6], @{ $lines[6] };
    }
    if (-1 != $lines[5][1]) {
        print join ' ', $lines[5][1], $lines[1][3], $lines[4][7],
                        $lines[4][6], @{ $lines[6] };
    }
}

【讨论】:

  • 非常感谢!你能告诉我应该把文件名放在哪里吗?我从未使用过 Perl。如果我的文件名是 data.dat,我的脚本应该是什么样子?
  • @polishastronomer:将脚本另存为whatever.pl,使其可执行(chmod a+x whatever.pl),以./whatever.pl data.dat 运行。
  • 完美运行!非常感谢你的帮助! :)
【解决方案2】:

在awk中,变量NR保存了行号,所以表达式

NR % 8 == 6 { ..... }

将选择第 6、14、22 行等。您只需要一个计数器,但变量会自动初始化为零,因此您可以使用这样的表达式获得序列号(第 6 行为 1,第 14 行为 2,依此类推)

++seqno

希望对您有所帮助....

【讨论】:

    【解决方案3】:

    awk 中的另一种解决方案

    awk '{if(NR%8==2){a=$3;b=$4};if(NR%8==4){a=$8","$7","a};if(NR%8==5){b=$8","$7","b};if(NR%8==6){c=$1;d=$2};if(NR%8==7){if(c!=-1.000000)print a,$0;if(d!=-1.000000)print b,$0 }}' inputfilename
    

    如果我按以下方式破坏上述命令

    awk '{
         if(NR%8==2){a=$3;b=$4};
         if(NR%8==4){a=$8","$7","a};
         if(NR%8==5){b=$8","$7","b};
         if(NR%8==6){c=$1;d=$2};
         if(NR%8==7){
                   if(c!=-1.000000)print a,$0;
                   if(d!=-1.000000)print b,$0 
                    }
         }' inputfilename
    

    我从头开始将输出详细信息存储在 a 和 b 中,同时逐行读取文件,例如 NR%8==2 是第 2 行,NR%8==4 是文件的第 4 行,依此类推。在第 7 行 (NR%8==7),我正在检查从第 6 行 (NR%8==6) 存储的值 c 和 d,如果 c 和 d 的值不匹配,我们将打印第 7 行内容的输出.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 2021-10-29
      • 1970-01-01
      相关资源
      最近更新 更多