Использование grep для определения неправильных заголовков

У меня есть несколько сотен документов, где каждый заголовок имеет вид:

# Some title here {.WORD} 

Я хочу идентифицировать с помощью grep каждый заголовок, который не соответствует этому стандарту. Однако строки, начинающиеся только с #, не должны обнаруживаться.

 ## | OK # Lorem .tip} | NOT OK # LIPSUM {.tip | NOT OK ### Lipsum {.hello word} | OK # Title | NOT OK ######## Title {.challenge} | OK 

Я написал следующее регулярное выражение, чтобы решить эту ситуацию

 ^##* .*(?<!{.*})$ 

Однако синтаксический анализатор жалуется на то, что «утверждение позади не имеет фиксированной длины». Как можно исправить приведенное выше выражение регулярного выражения, чтобы исправить это?

 $ grep -vE '^#+( [ [:alpha:]]+ \{\.[ [:alpha:]]+\})?$' file # Lorem .tip} # LIPSUM {.tip # Title 

Расширенное регулярное выражение соответствует строкам «ОК». С -v мы просим увидеть строки, которые не совпадают.

Шаблон требует, чтобы строка начиналась с некоторого количества символов # . Остальная часть строки является необязательной, но если она существует, она должна начинаться с пробела, затем содержать несколько букв, возможно, с пробелами между ними, а затем заключительный пробел перед { . Часть внутри { и } должна начинаться с точки и может содержать некоторое количество букв и пробелов.

При использовании lookaheads / lookbehinds вы не можете помещать в них любые типы регулярных выражений типа glob, они могут быть только строками фиксированной длины.

Вы можете использовать PCRE средство grep сделать это:

 $ grep -vP "(?<=#)*\s*\w*\s*{.*}|^[#]+$" afile # Lorem .tip} # LIPSUM {.tip # Title 

Как это работает:

  • (?<=#)* ищет хотя бы 1 или более #
  • \s*\w*\s* ищет последовательность пробел + слово + пробел - это ноль или более
  • {.*} ищет { сопровождаемый по крайней мере 1 символом и закрытием }
  • |^[#]+$" ищет строку, которая просто # или больше