Когда использование awk/pattern/{печатает “текст”}/patern/{печать “”} ЕЩЕ там шаблон?

На аппаратных RAID-контроллерах, восстанавливая массив с большими дисками не приведет к большему массиву. Предыдущие разы я создал новые массивы рядом со старыми.

Мой последний план обновления был:

  1. скопируйте данные по 2 дискам (как дополнительное резервное копирование)
  2. Создайте новый массив с остающимися большими дисками (RAID 5 все еще даст Вам больший массив затем последний),
  3. Переместите данные в новый массив
  4. Удалите старый массив
  5. Вырастите новый массив с этими 2 дополнительными дисками
22
28.11.2011, 21:09
3 ответа

Упрощенный подход с awk

awk '/R1/ {print "=>" $0;next} /R2/{print "*" $0;next} 1' text.file

[jaypal:~/Temp] cat text.file 
R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

[jaypal:~/Temp] awk '/R1/ { print "=>" $0;next} /R2/{print "*" $0;next}1' text.file
=>R1 12 324 3453 36 457 4 7 8
*R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
[jaypal:~/Temp] 

Выход шаблона {действие} операторы:

  • /R1/ { print "=>" $0;next} : Это означает наличие строк /R1/ действие печати => будет сделан. next остальная часть средств awk операторов будет проигнорирована, и на следующую строку посмотрят.

  • /R2/{print "*" $0;next} : Это означает строки, соответствующие pattern /R2/ действие печати * будет сделан. Когда awk обработка запускается, первое pattern {action} оператор будет проигнорирован как pattern /R1/ не будет верно для наличия строк /R2/. Настолько второй pattern {action} оператор будет сделанный на строке. next снова означал бы, что мы больше не хотим обрабатывать и awk должным образом перейдет к следующей строке.

  • 1 печать все строки. Когда просто условие предоставляется без {action}, значения по умолчанию awk к использованию {print}. Здесь условие 1 который интерпретируется как верный, таким образом, это всегда успешно выполняется. Если мы добираемся до этой точки, это потому что первое и второе pattern {action} операторы были проигнорированы или обойдены (для строк, не содержащих /R1/ и /R2/), таким образом, действие печати по умолчанию будет сделано для остающихся строк.

27
27.01.2020, 19:42
  • 1
    Кажется, незначительно выполняет самое быстрое из всех отправленных решений. –  Chris Down 28.11.2011, 23:50
  • 2
    я не уверен синтаксический сахар, является правильным словом здесь... Это - просто синтаксис. –  Daniel Hershcovich 30.11.2011, 13:40

awk реализует обычных подозреваемых когда дело доходит до условных выражений. Это - хорошая идея использовать printf вместо print для задания, которое Вы желаете сделать на соответствии.

awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'
7
27.01.2020, 19:42
  • 1
    Вам действительно не нужно if-then-else для этого. –  jaypal singh 28.11.2011, 23:44
  • 2
    В то время как это работает отлично, это не идиоматично. Разумное использование next важный инструмент в программировании awk. –  dmckee --- ex-moderator kitten 29.11.2011, 01:09
  • 3
    я не понимаю точку использования printf здесь. Его единственное преимущество (если Вы не делаете более необычное форматирование, чем конкатенация) состоит в том, что это не добавляет новую строку, которая не релевантна здесь. –  Gilles 'SO- stop being evil' 29.11.2011, 01:43
  • 4
    Это - парадоксальный и неожиданный результат. Неукрашенный print только должен произвести $0 тогда как printf должен проанализировать строку формата. –  jw013 30.08.2012, 00:58

Chris Down уже показал, как еще можно добраться для regexps при помощи явного 'если' оператор в блоке. Можно добраться, также получают тот же эффект некоторыми другими путями, хотя его решение, вероятно, лучше.

Нужно записать треть regex, который будет только соответствовать тексту, не подобранному другими в Вашем случае, это выглядело бы примерно так:

awk '/^R1/ { print "=>" $0}
     /^R2/ { print "*" $0}
     /^[^R]/ || /^R[^12]/ { print $0 } '

Отметьте, это использует привязанный regexps - ^ в начале regexps будет только соответствовать в начале строки - Ваши исходные шаблоны не сделали этого, которое замедляет соответствие немного, поскольку это проверит все символы на строке вместо того, чтобы пропустить до следующей строки. Третьи ("еще") случаются, будет соответствовать строке, которая начинается с некоторого символа, который не является 'R' ([^R]), или это начинается с 'R', сопровождаемого символом, который не является '1' или '2' (R [^12]). Два различных значения ^ несколько сбивают с толку, но та ошибка была сделана давным-давно и не будет изменена в ближайшее время.

Для использования дополнительного regexps они действительно должны быть привязаны, поскольку иначе [^R] соответствовал бы, например, 1 после него. Поскольку очень простые regexps как Вы имеют, этот подход может быть полезным, но поскольку regexps становятся более сложными, этот подход станет неуправляемым. Вместо этого можно использовать переменные состояния для каждой строки, как это:

awk '{ handled = 0 }
     /^R1/ { print "=>" $0; handled = 1}
     /^R2/ { print "*" $0; handled = 1}
     { if (!handled) print $0 } '

Это устанавливает обработанный для обнуления для каждой новой строки, затем к 1, если она соответствует любому из двух regexps, и наконец, если это - все еще нуль, выполняет печать 0$.

5
27.01.2020, 19:42
  • 1
    Нужно отметить, что на больших файлах оба менее эффективны, чем использование условных выражений (как показано здесь). rfile всего 10 000 строк повторенного набора данных корреспондента. –  Chris Down 28.11.2011, 21:51
  • 2
    if (!handled) Фу! Использовать next прекратить рассматривать другие действия. –  dmckee --- ex-moderator kitten 29.11.2011, 01:05
  • 3
    +1 для if (!handled). Общие, гибкие, допускающие повторное использование решения хороши. Что, если следующий человек, у которого есть этот вопрос, хочет сделать больше обработки после печати? Ответы с next не поддерживайте это. –  Scott 01.07.2014, 22:45

Теги

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