Использование AWK для цикла в качестве входных данных для поиска и замены

Попробуйте это:-

< VirtualHost home.mydomain.com:80>

ServerName home.mydomain.com

order Allow,Deny

Allow from 127.0.0.1/8

Allow from mydomain.com

< /VirtualHost>

Для получения дополнительной информации см.http://httpd.apache.org/docs/2.2/en/mod/mod_authz_host.html

1
14.08.2019, 04:41
3 ответа

Один из способов сделать это — построить одно регулярное выражение из полей 3 -конца каждой строки в Ref.txt, соединив их в цепочку с |, сохранив это в ассоциативном массиве с ключом $1стоимость.

Затем вы можете циклически переключать клавиши для каждого $1Seq.txt:

awk -F, '
  NR==FNR {
    # construct a single ERE as $3|$4|$5|etc. keyed on $1
    for(i=3;i<=NF;i++) r[$1] = r[$1] == "" ? $i : r[$1] "|" $i;
    next
  } 
  {
    # test $1 against each ERE and substitute the first matching key
    for(k in r) {
      if ($1 ~ r[k]) {
        $1 = k; 
        break
      }
    }
  }
  1
' Ref.txt Seq.txt
2
27.01.2020, 23:41

Если вы ленивы, как я, вы не хотите иметь дело с массивами и циклами и оставить это на ваше усмотрение. Вот почему я предпочитаю sedи просто добавляю те Ref.txtстроки (, которые обозначены запятой )в пробеле с H. На самом деле я добавляю еще одну запятую, чтобы знать, что шаблоны всегда находятся между двумя запятыми. Итак, вместе это /,/{s/$/,/;H;d;}.

Теперь, для каждой строки Seq.txt, я добавляю пробел к своей эталонной стопке с помощью Gи позволяю команде sзаменить шаблон на шаблон, найденный в стопке. Как часто регулярное выражение легче написать, чем прочитать.

Давайте теперь посмотрим на пространство шаблонов:

ABCDEFG\n\nABCDEFG,15147,ABC,ABCD,ABCDE\nHIJKLMN,500,HIJKLM,HIJKL,HIJK
\_____/    \_____/       \_/
replace    by this  if  match
  • Заменяемая деталь находится в начале(^)с соответствующей деталью([A-Z]+)и некоторыми деталями до и после([A-Z]*)
  • Замена представляет собой последовательность между новой строкой и запятой:\n[A-Z]*,
  • совпадение — это шаблон между двумя запятыми, обратная ссылка из первой части:,\1,

Все вместе это дает

sed -E '/,/{s/$/,/;H;d;};G;s/^[A-Z]*([A-Z]{1,})[A-Z]*\n.*\n([A-Z]*),[A-Z0-9,]*,\1,.*/\2/;P;d' Ref.txt Seq.txt
-1
27.01.2020, 23:41

Вы можете выполнить это с помощью sed, используя только конструкции Posix, как показано здесь:

$ sed -ne '
   /,/!G
   y/\n_/_\n/
   s/^\([^_][^_]*\).*__\(.*_\)\{0,1\}\([^,]*\),[^,]*,[^_]*,\1,.*/\3/p
   s/^[^_]*__//;s/$/,/
   y/_\n/\n_/
   /\n/!H
' Ref.txt Seq.txt

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

Perlтакже можно использовать здесь, не прибегая к регулярным выражениям:

$ perl -F, -lane '
   if ( @ARGV ) {
     $h{$_} = $F[0] for @F[2..$#F];
     next;
   }
   my $seq = $_;
   my($k) = grep { ! index($seq, $_) } keys %h;
   print $h{$k};
' Ref.txt Seq.txt
0
27.01.2020, 23:41

Теги

Похожие вопросы