2016-06-09 3 views
0

отводился разделителями табуляции вход, как это:Использование AWK, чтобы найти все слова, совпадающие все шаблоны

us-west-2  vpc-abcdefg 42 elb-foo-bar-baz 
us-east-1  foo  vpc-123455  eipalloc-bar 

Я хочу использовать awk, чтобы сделать некоторые шаблону таким образом, что я могу найти все слова, который соответствует vpc-*, elb-*, или eipalloc-* на входе. Я также хочу, чтобы awk читал только вход за один проход.

Мои результаты должны быть пространственно-разделителями совпадающая значения:

vpc-abcdef vpc-123455 
elb-foo-bar-baz 
eipalloc-bar 

Как будет идти об этом?

+0

Если вы имеете в виду "начинается с" 'VPC-', 'ELB-', и т.д., то почему бы не разделить на '-'. что ты уже испробовал? Это не служба написания кода. – cdarke

+0

Я не вижу, как раскол на '-' мне поможет. –

+0

Вы можете использовать 'split()' on '-', а затем проверить первый элемент. Я предполагаю, что шаблоны, которые вы указали, являются конструкциями glob - 'awk' использует Extended Regular Expressions. что ты уже испробовал? – cdarke

ответ

2

Попробуйте это (где gash.txt ваш входной файл):

awk -f - gash.txt << '__END__' 
    BEGIN { 
     tags["vpc"] = "" 
     tags["elb"] = "" 
     tags["eipalloc"] = "" 
    } 
    { for (i=1; i <= NF; i++) { 
      n = split($i, a, "-") 
      if (a[1] in tags) 
       print $i 
     } 
    } 

__END__ 

ассоциативный массив в BEGIN блоке, вероятно, является излишним, но это делает его легче добавить больше целей в будущем.

EDIT:

я понял, что я не производил выход в том же стиле, как это требуется, извинения. Пользуясь тем, что ассоциативный массив становится довольно легко изменить:

awk -f - gash.txt << '__END__' 
    BEGIN { 
     tags["vpc"] = "" 
     tags["elb"] = "" 
     tags["eipalloc"] = "" 
    } 
    { for (i=1; i <= NF; i++) { 
      n = split($i, a, /-/) 
      if (a[1] in tags) 
       tags[a[1]] = tags[a[1]] $i " " 
     } 
    } 
    END { 
     for (item in tags) 
      print tags[item] 
    } 

__END__ 
+0

Зачем вам было сказано awk использовать stdin в качестве файла сценария, а затем использовать здесь doc для предоставления скрипта, а не только скрипта awk? Gash.txt? Кроме того, это неверно совпало бы, если поле содержало только «vpc» вместо «vpc-», поскольку OP, похоже, хочет. Вы также не используете 'n', поэтому никакая точка не задает его, а третий arg для split() является регулярным выражением, а не строкой, поэтому вы должны использовать regexp, а не строку, разделители:' split ($ i, a,/- /) '. –

+0

@EdMorton: многие люди предпочитают встраивать 'awk' внутри сценария bash, например, имя файла может быть получено с использованием' bash' (и 'bash' - это тег для этого вопроса).Наличие отдельного файла затрудняет управление кодом, что является компромиссом для неэффективности данного документа. Я разделился на '-', чтобы он не забирал' vac ', если за ним не следует дефис (проверено). Для одного символа '/ /' являются необязательными - они не имеют значения. – cdarke

+0

Я не предлагаю использовать отдельный файл для скрипта, я предлагаю использовать обычный awk-синтаксис 'awk 'script' file' вместо того, чтобы сделать его излишне сложным с помощью скрипта awk -f-file << '__END__' '__END __' '. Я понимаю, почему вы разделили этот путь, но тогда ваш сценарий, как написано, не может различать поле с именем 'vpc' и которое начинается с' vpc-'по желанию (подсказка - вы можете использовать' n', чтобы исправить это). Использование ограничителей строк для регулярного выражения просто не имеет смысла, так как это ** regexp **, поэтому используйте только ограничители строк, когда у вас есть цель, например. конкатенация с переменной. –

0

рассмотреть возможность использования grep с -o, который извлечет матчи:

% grep -oE '(vpc|elb|eipalloc)-[^ ]*' data.txt 
vpc-abcdefg 
elb-foo-bar-baz 
vpc-123455 
eipalloc-bar 

Я знаю, что это не дает точный формат вывода, но это может быть хорошо?

+0

Я тоже думал об этом подходе, но я не могу получить все совпадения 'vpc- *' в одной строке и т. Д. –

+1

@StephenChu: 'vac- *' является конструкцией glob, 'grep' принимает регулярное выражение (RE). В терминах RE 'vpc- *' означает «vpc, за которым следуют ноль или более дефисов». «*» В RE соответствует шаблону или символу слева, что не совпадает с тем, что происходит в globbing. – cdarke

+0

Я понимаю. Я не хотел путать решателя проблем, чтобы различать '*' или '[a-z0-9]', поскольку это не моя проблема. –

0

другой awk

$ awk -v RS='\t|\n' 'BEGIN{split("vpc- elb- eipalloc-",ks)} 
          {for(k in ks) if($0~ks[k]) a[k]=a[k]?a[k] FS $0:$0} 
         END{for(k in a) print a[k]}' file 

vpc-abcdefg vpc-123455 
elb-foo-bar-baz 
eipalloc-bar 
+0

Спасибо за это решение. –

Смежные вопросы