0

このパターンマッチを見つけようとしています。同じ行の最初の一致のみを一致させて表示したい。一致の 1 つ、4 番目のフィールドは 2 つのパターンのいずれかに一致する可能性があります。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つの方法は、次を探すことです:行で見つけた最初の「時間」、最初の英数字文字列のセット、およびコンマを含む/含まない最初の10進数値、それらすべてが同じ出力に出力されますライン。より一般的な説明は次のようになります。入力行が与えられた場合、パターン 1 の最初の出現、パターン 2 の最初の出現、およびパターン 3 の最初の出現 (それ自体は 2 つのパターンの「or」です) を出力の 1 行に出力し、安定している必要があります (つまり、入力に現れた順序を維持します)。少し複雑な例で申し訳ありませんが、これが Perl/Python のような完全な言語用の Unix ユーティリティを使用するスイート スポットであるかどうかも調べようとしています。したがって、これが 2 番目の一連の例の予想される結果です。

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 に答える