Unix объединяет два файла с регулярными выражениями, используя awk - PullRequest
1 голос
/ 06 апреля 2011

У меня есть один файл (lookup.txt), который содержит справочную таблицу, состоящую из списка регулярных выражений, с соответствующими данными (категориями и периодами).например,

INTERNODE|household/bills/broadband|monthly
ORIGIN ENERGY|household/bills/electricity|quarterly
TELSTRA.*BILL|household/bills/phone|quarterly
OPTUS|household/bills/mobile|quarterly
SKYPE|household/bills/skype|non-periodic

У меня есть другой файл (data.txt), который содержит список расходов, например:

2009-10-31,cc,-39.9,INTERNODE BROADBAND
2009-10-31,cc,-50,ORIGIN ENERGY 543546
2009-10-31,cc,-68,INTERNODE BROADBAND EXCESS CHARGES
2009-10-31,cc,-90,TELSTRA MOBILE BILL
2009-11-02,cc,-320,TELSTRA HOME BILL
2009-11-03,cc,-22.96,DICK SMITH
2009-11-03,cc,-251.24,BUNNINGS
2009-11-04,cc,-4.2,7-ELEVEN

Я хочу объединить эти два элемента, в результате чего четвертый столбец вФайл data.txt соответствует регулярному выражению из первого столбца файла lookup.txt.

Таким образом, вывод будет:

2009-10-31,cc,-39.9,INTERNODE BROADBAND,household/bills/broadband,monthly
2009-10-31,cc,-50,ORIGIN ENERGY 543546,household/bills/electricity,quarterly
2009-10-31,cc,-68,INTERNODE BROADBAND EXCESS CHARGES,household/bills/broadband,monthly
2009-10-31,cc,-90,TELSTRA MOBILE BILL,household/bills/phone,quarterly
2009-11-02,cc,-320,TELSTRA HOME BILL,household/bills/phone,quarterly
2009-11-03,cc,-22.96,DICK SMITH
2009-11-03,cc,-251.24,BUNNINGS
2009-11-04,cc,-4.2,7-ELEVEN

Я получил это с помощью цикла bash,циклический поиск, выполнение greps и добавление дополнительных столбцов при использовании sed, но это очень медленно.Так что было интересно, есть ли более быстрый способ сделать это, говоря, используя awk.

Любая помощь будет оценена.

Ответы [ 5 ]

3 голосов
/ 06 апреля 2011
$ awk -F'|' 'FNR==NR{a[$1]=$2","$3;next}{m=split($0,b,",");for(i in a){if(b[4]~i){print $0","a[i];next}}}1' lookup file
2009-10-31,cc,-39.9,INTERNODE BROADBAND,household/bills/broadband,monthly
2009-10-31,cc,-50,ORIGIN ENERGY 543546,household/bills/electricity,quarterly
2009-10-31,cc,-68,INTERNODE BROADBAND EXCESS CHARGES,household/bills/broadband,monthly
2009-10-31,cc,-90,TELSTRA MOBILE BILL,household/bills/phone,quarterly
2009-11-02,cc,-320,TELSTRA HOME BILL,household/bills/phone,quarterly
2009-11-03,cc,-22.96,DICK SMITH
2009-11-03,cc,-251.24,BUNNINGS
2009-11-04,cc,-4.2,7-ELEVEN
1 голос
/ 06 апреля 2011

Вы можете сделать это на Python:

#!/usr/bin/python
import csv, re
lookup = []
with open('lookup.txt') as f:
    for rec in csv.reader(f, delimiter='|'):
        lookup.append((re.compile(rec[0]), rec[1:]))
with open('data.txt') as f:
    for rec in csv.reader(f, delimiter=','):
        for rexp, fields in lookup:
            if rexp.match(rec[3]):
                rec.extend(fields)
                break
        print ','.join(rec)

Для ваших файлов lookup.txt и data.txt возвращается менее чем за 0,3 с:

2009-10-31,cc,-39.9,INTERNODE BROADBAND,household/bills/broadband,monthly
2009-10-31,cc,-50,ORIGIN ENERGY 543546,household/bills/electricity,quarterly
2009-10-31,cc,-68,INTERNODE BROADBAND EXCESS CHARGES,household/bills/broadband,monthly
2009-10-31,cc,-90,TELSTRA MOBILE BILL,household/bills/phone,quarterly
2009-11-02,cc,-320,TELSTRA HOME BILL,household/bills/phone,quarterly
2009-11-03,cc,-22.96,DICK SMITH
2009-11-03,cc,-251.24,BUNNINGS
2009-11-04,cc,-4.2,7-ELEVEN
0 голосов
/ 06 апреля 2011

Awk действительно предназначен для обработки одного потока данных по одной записи за раз, поэтому он не является подходящим инструментом для этой работы.Это будет десятиминутное упражнение на Perl или другом языке, который больше ориентирован на программирование общего назначения.

Если вы хотите делать все это в awk, напишите один сценарий, чтобы сгенерировать второй сценарий awk изваш поисковый файл, который обрабатывает данные, а затем запустите второй скрипт.

0 голосов
/ 06 апреля 2011

Если у вас не было регулярных выражений, вы можете использовать join.Сколько регулярных выражений lookup.txt имеет?Если это просто так, просто разверните его и отбросьте эту функцию.

0 голосов
/ 06 апреля 2011

Вы можете сделать это в Perl.Преимущество Perl (или Python) в том, что у них есть библиотеки для работы с CSV-файлами.Ваши примеры достаточно просты, но что произойдет, если вы заключите запятую в двойные кавычки?Или как насчет utf8?и т.д.

Стандартная библиотека Perl для этого Текст: CSV_XS .Однако, это немного многословно, и я предпочитаю Parse :: CSV , который является оберткой вокруг Text :: CSV_XS.

#!/usr/bin/perl

use strict;
use warnings;
use Parse::CSV;

my %lookup;
my $l = Parse::CSV->new(file => "lookup.txt", sep_char => '|');
while (my $row = $l->fetch) {
   my $key = qr/$row->[0]/;
   $lookup{$key} = [$row->[1,]];
}

my $d = Parse::CSV->new(file => "data.txt");
while (my $row = $d->fetch) {
   foreach my $regex (keys %lookup) {
      if ($row->[3] =~ $regex) {
         push @$row, @{$lookup{$regex}};
         last;
      }
   }
   print join(",", @$row), "\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...