оболочка unix: заменить на словарь - PullRequest
3 голосов
/ 17 июня 2011

У меня есть файл, который содержит некоторые данные, как это

2011-01-02 100100 1 
2011-01-02 100200 0
2011-01-02 100199 3
2011-01-02 100235 4

и иметь "словарь" в отдельном файле

100100 Event1
100200 Event2
100199 Event3
100235 Event4

и я знаю, что

0 - warning
1 - error
2 - critical
etc...

Мне нужен какой-нибудь скрипт с sed / awk / grep или что-то еще, что помогает мне получать такие данные

100100 Event1 Error
100200 Event2 Warning
100199 Event3 Critical
etc

будет благодарен за идеи, как это сделать наилучшим образом, или за рабочий пример.

обновление

иногда у меня есть такие данные

2011-01-02 100100 1
2011-01-02 sometext 100200 0
2011-01-02 100199 3
2011-01-02 sometext 100235 4

где sometext = любые 6 символов (возможно, это полезная информация)
в этом случае мне нужны целые данные:

2011-01-02 sometext EventNameFromDictionary Error

или без "sometext"

Ответы [ 3 ]

6 голосов
/ 17 июня 2011
awk 'BEGIN {
 lvl[0] = "warning"
 lvl[1] = "error"
 lvl[2] = "critical"
 }
NR == FNR {
  evt[$1] = $2; next
  } 
{
  print $2, evt[$2], lvl[$3]
  }' dictionary infile
0 голосов
/ 19 июня 2011

Добавление нового ответа для нового требования и из-за ограниченных опций форматирования внутри комментария:

awk 'BEGIN {
 lvl[0] = "warning"
 lvl[1] = "error"
 lvl[2] = "critical"
 }
NR == FNR {
  evt[$1] = $2; next
  } 
{
  if (NF > 3) {
    idx = 3; $1 = $1 OFS $2
    }
  else idx = 2  
  print $1, $idx in evt ? \
    evt[$idx] : $idx, $++idx in lvl ? \
      lvl[$idx] : $idx
  }' dictionary infile

Вам не нужно экранировать новые строки внутри третичного оператора, если вы используете GNU awk .

Некоторые реализации awk могут иметь проблемы с этой частью:

$++idx in lvl ? lvl[$idx] : $idx

Если вы используете одну из них, измените ее на:

$(idx + 1) in lvl ? lvl[$(idx + 1)] : $(idx + 1)

ОК, комментарии добавлены:

awk 'BEGIN {
 lvl[0] = "warning"       # map the error levels
 lvl[1] = "error"                
 lvl[2] = "critical"      
 }                        
NR == FNR {               # while reading the first
                          # non-empty input file
  evt[$1] = $2          # build the associative array evt
  next                    # skip the rest of the program
                          # keyed by the value of the first column
                          # the second column represents the values
  }                       
{                         # now reading the rest of the input
  if (NF > 3) {           # if the number of columns is greater than 3
    idx = 3               # set idx to 3 (the key in evt)
    $1 = $1 OFS $2       # and merge $1 and $2
    }                     
  else idx = 2            # else set idx to 2
  print $1, \              # print the value of the first column
    $idx in evt ? \    # if the value of the second (or the third,
                  \       # depeneding on the value of idx), is an existing
                  \       # key in the evt array, print its value
    evt[$idx] : $idx, \ # otherwise print the actual column value
    $++idx in lvl ?   \   # the same here, but first increment the idx 
     lvl[$idx] : $idx       # because we're searching the lvl array now     
  }' dictionary infile
0 голосов
/ 17 июня 2011

Надеюсь, с Perl тоже все в порядке:

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

open(DICT, 'dict.txt') or die;
my %dict = %{{ map { my ($id, $name) = split; $id => $name } (<DICT>) }};
close(DICT);

my %level = ( 0 => "warning", 
              1 => "error",
              2 => "critical" );

open(EVTS, 'events.txt') or die;

while (<EVTS>)
{
    my ($d, $i, $l) = split;
    $i = $dict{$i}  || $i;  # lookup
    $l = $level{$l} || $l;  # lookup 
    print "$d\t$i\t$l\n";
}

Вывод:

$ ./script.pl
2011-01-02      Event1  error
2011-01-02      Event2  warning
2011-01-02      Event3  3
2011-01-02      Event4  4
...