Является ли выражение /start/,/end/range когда-либо полезным в awk?

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

/start/,/end/

в awk, потому что хотя он делает тривиальный случай, когда вы хотите распечатать соответствующий текст, включая начальную и конечную строки, немного более краткими, чем альтернатива *:

/start/{f=1} f{print; if (/end/) f=0}

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

f{if (/end/) f=0; else print} /start/{f=1}

но если вы начали с /start/,/end/, вам нужно отказаться от этого подхода в пользу того, что я только что написал, или вам нужно написать что-то вроде:

/start/,/end/{ if (!/start|end/) print }

то есть. дублируйте условия, которые нежелательны.

Затем я увидел вопрос, который потребовал идентифицировать LAST end в файле и где в решении было использовано выражение диапазона, и я подумал, что это может иметь какое-то значение (см. qaru.site/info/449989/...).

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

Итак, есть ли у кого-нибудь пример, где выражение диапазона действительно добавляет заметное значение в решение?

* Раньше я использовал:

/start/{f=1} f; /end/{f=0}

но слишком много раз я обнаружил, что мне нужно было сделать что-то дополнительное, когда f истинно и /end/ найдено (или, если поместить его другим способом, ТОЛЬКО что-то делать, когда /end/ найдено IF f). поэтому теперь я просто стараюсь придерживаться чуть менее коротких, но гораздо более надежных и расширяемых:

/start/{f=1} f{print; if (/end/) f=0}

Ответ 1

Интересно. Я также часто начинаю с выражения диапазона, а затем перейду на использование переменной.

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

awk '/start/,/end/{if(/ppp/)print}' file

с этим вводом:

start
dfgd gd
ppp 1
gfdg
fd gfd
end
ppp 2 
ppp 3
start
ppp 4
ppp 5
end
ppp 6
ppp 7
gfdgdgd

будет производить:

ppp 1
ppp 4
ppp 5

- Разумеется, можно также использовать:

awk '/start/{f=1} /ppp/ && f; /end/{f=0}' file

Но это длиннее и несколько менее читаемо.

Ответ 2

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

Итак, есть ли у кого-нибудь пример, где выражение диапазона действительно добавляет заметное значение в решение?

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

Фильтровать журналы в пределах диапазона времени

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

awk '/^2015-06-30T12:00:00Z/,/^2015-06-30T13:00:00Z/'

Извлечь документ из файла

awk '/---- begin file.data ----/,/---- end file.data ----/'

Это можно использовать для связывания ресурсов со сценариями оболочки (с помощью cat), для извлечения частей сообщений, подписанных GPG (подготовленных с помощью --clearsign) или, более того, из MIME-сообщений.

Файлы процесса LaTeX

Шаблон диапазона может использоваться для соответствия среде LaTeX, поэтому, например, мы можем выбрать тезисы всех статей в нашем каталоге:

awk '/begin{abstract}/,/end{abstract}/' *.tex

или все теоремы, чтобы подготовить базу данных теорем!

awk '/begin{theorem}/,/end{theorem}/' *.tex

или напишите linter, чтобы в теоремах не содержались цитаты (если мы рассматриваем это как плохой стиль):

awk '
  /begin{theorem}/,/end{theorem}/ { if(/\\cite{/) { c+= 1 } }
  END { printf("There were %d bad-style citations.\n", c) }
'

или таблицы предварительной обработки и т.д.