0

我正在尝试找到这种模式匹配。我想匹配并仅显示同一行中的第一个匹配项。其中一个匹配项,第四个字段可以匹配两种模式中的任何一种,即;A,BCD.EF 或 AB.CD 。一个例子是

Example 1:
12:23 23:23 ASDFGH 1,232.00 22.00
21:22 12:12 ASDSDS 22.00 21.00 

预期的输出将是

Expected Result 1:
12:23 ASDFGH 1,232.00
21:22 ASDSDS 22.00

使用我对 grep 和 stackoverflow 的一点了解,我已经走到了这一步。

< test_data.txt grep -one "[0-9]/[0-9][0-9]\|[0-9]*,[0-9]*.[0-9][0-9]\|[0-9]*.[0-9][0-9]" | awk -F ":" '$1 == y { sub(/[^:]:/,""); r = (r ? r OFS : "") $0; next } x { print x, r; r="" } { x=$0; y=$1; sub(/[^:]:/,"",x) } END { print x, r }'

任何使这更简单或更清洁并实现完整功能的想法。

更新 1:其他几个例子可能是:

Example 2:
12:21 11111 11:11 ASADSS 11.00 11.00
22:22 111232 22:22 BASDASD 1111 1,231.00 1,121.00
  1. 某些行中可能有更多字段。
  2. 字段的顺序也不一定保留。我可以通过分别处理具有不同顺序的文件或以某种方式将它们转换为这个顺序来解决这个问题。所以这个条件可以放宽。

更新 2:似乎我的问题并不清楚。因此,查看它的一种方法是寻找:我在一行上找到的第一个“时间”,第一组字母数字字符串和第一个带/不带逗号的十进制值,所有这些都打印在相同的输出上线。更通用的描述是,给定输入行,在输出的一行中打印模式 1 的第一次出现、模式 2 的第一次出现和模式 3 的第一次出现(它本身是两个模式的“或”),然后必须是稳定的(即;保持它们在输入中出现的顺序)。抱歉,这是一个有点复杂的例子,我也在尝试了解这是否是使用 Unix 实用程序来使用 Perl/Python 等完整语言的最佳选择。因此,这是第二组示例的预期结果。

Expected Result 2:
12:21 ASADSS 11.00
22:22 BASDASD 1,231.00
4

2 回答 2

3
#!/usr/bin/awk -f

BEGIN {
    p[0] = "^[0-9]+:[0-9]{2}$"
    p[1] = "^[[:alpha:]][[:alnum:]]*$"
    p[2] = "^[0-9]+[0-9,]*[.][0-9]{2}$"
}

{
    i = 0
    for (j = 1; j <= NF; ++j) {
        for (k = 0; k in p; ++k) {
            if ($j ~ p[k] && !q[k]++ && j > ++i) {
                $i = $j
            }
        }
    }
    q[0] = q[1] = q[2] = 0
    NF = i
    print
}

输入:

12:23 23:23 ASDFGH 1,232.00 22.00
21:22 12:12 ASDSDS 22.00 21.00 
12:21 11111 11:11 ASADSS 11.00 11.00
22:22 111232 22:22 BASDASD 1111 1,231.00 1,121.00

输出:

12:23 ASDFGH 1,232.00
21:22 ASDSDS 22.00
12:21 ASADSS 11.00
22:22 BASDASD 1,231.00
于 2013-09-20T00:09:18.987 回答
1

Perl-regex 风格应该可以解决这个问题:

(\d\d:\d\d).*?([a-zA-Z]+).*?((?:\d,\d{3}\.\d\d)|(?:\d\d\.\d\d))

它将捕获以下数据(处理您单独提供的每一行):

RESULT$VAR1 = [
          '12:23',
          'ASDFGH',
          '1,232.00'
        ];
RESULT$VAR1 = [
          '21:22',
          'ASDSDS',
          '22.00'
        ];
RESULT$VAR1 = [
          '12:21',
          'ASADSS',
          '11.00'
        ];
RESULT$VAR1 = [
          '22:22',
          'BASDASD',
          '1,231.00'
        ];

示例 perl script.pl:

#!/usr/bin/perl
use strict;
use Data::Dumper;

open my $F, '<', shift @ARGV;

my @strings = <$F>;
my $qr = qr/(\d\d:\d\d).*?([a-zA-Z]+).*?((?:\d,\d{3}\.\d\d)|(?:\d\d\.\d\d))/;

foreach my $string (@strings) {
    chomp $string;
    next if not $string;
    my @tab = $string =~ $qr;
    print join(" ", @tab) . "\n";
}

运行为:

perl script.pl test_data.txt

干杯!

于 2013-09-19T22:51:49.580 回答