Да
:g/^func/.;/^[^!]/-1 print
Обновление
Было предложено объяснение ... вот так ... vi (1) мощно отчасти потому, что является расширением адресации курсора для оригинального строкового редактора ed (1) Кена Томпсона. (ed (1) и его дополнительный ответ ex
по-прежнему доступен в Linux после всех этих лет, хотя и в форме клона, как само vi.) Ed и его ранние братья и юниксы были первыми программами, где использовались регулярные выражения.
Хорошо, создайте файл с примерно 26 строками, по одной для каждой буквы вашего алфавита, и начните с vi, ed или ex. (Для ed или ex, пропустите символы:.) Попробуйте:
:1;/m/p
Общий вид команды vi: addr, команда addr2
В моем примере команда просто p
для печати. addr1 и addr2 обычно являются номером строки или регулярным выражением, используя / re / для поиска вниз или? re? искать вверх. Попробуйте /c/;/g/p
, что побуждает меня объяснить: ;
заставляет редактор переключиться на строку, найденную по первому адресу, прежде чем он оценит второй адрес. Это не всегда имеет значение в режиме обертывания по умолчанию, но если вы введете :set nows
(не в ed), то шаблоны поиска не будут перенесены, и разница между ,
и ;
станет больше.
Самая важная команда режима строки не использовалась в моем примере, но ее следует упомянуть здесь: :s/pattern/replacement/
или :s/pattern/replacement/g
. Эта команда, конечно, может принимать адреса, поэтому типичная команда 1,$s/old/new/g
$
идентифицирует последнюю строку. Адрес по умолчанию для большинства команд - это текущая строка, но для команды global
или g
по умолчанию используется 1,$
и она имеет общий вид
addr1, addr2 g /pattern/ any_linemode_command
Например, скажем, я Джефф но я хочу обвинить Джоэл в различных типах критических ошибок в журналах , Мне нужно быть скрытным и не менять Джеффа на простые предупреждающие строки, поэтому мне нужно:
g/critical.*error/s/Jeff/Joel/
Это будет запускать команду замены в каждой строке файла с шаблоном "критическая что-нибудь ошибка", а затем просто изменить Джефф на Джоэл.
Так что теперь ответ должен быть довольно ясным. Команда работает следующим образом: в каждой строке файла проверьте, начинается ли строка с / ^ func / (func в начале строки) и, если это так, начните с .
(текущая строка), затем , сбрасывая текущий адрес в эту строку (;
), ищите строку, которая НЕ начинается с !
, и, если она найдена, вычтите одну из найденного номера строки (немного назад до последнего фактического комментария), а затем просто запустите команду print
.