Нахождение неправильных заголовков YAML

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

--- header: . . . title: some header: . . . more headers: level: . . . --- 

Куда . , , только представляет больше заголовков. Заголовки не содержат отступов. Используя следующее выражение, я смог извлечь заголовок YAML из каждого файла.

 grep -Przo --include=\*.md "^---(.|\n)*?---" . 

Теперь я хочу перечислить неправильные заголовки YAML.

  • Каждый заголовок YAML должен иметь title: some text
  • Каждый заголовок YAML должен иметь language: [az]{2}
  • Он должен содержать либо external: .* Либо author: .* .
  • Расположение title: level: external: и language: варьируется.

Я пытался сделать что-то вроде

 grep -L --include=\*.md -e "external: .*" -e "author: .* ." 

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

 grep -Przo --include=\*.md "^---(.|\n)*?---" . | xargs -0 grep "title:"; 

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

Примеры:

 --- title: Rull-en-ball level: 1 author: Transkribert og oversatt fra [Unity3D](http://unity3d.com) translator: Bjørn Fjukstad license: Oversatt fra [unity3d.com](https://unity3d.com/learn/tutorials/projects/roll-ball-tutorial) language: nb --- 

Правильный YAML, имеет автора, язык и название.

 --- title: Mini Golf level: 2 language: en external: http://appinventor.mit.edu/explore/ai2/minigolf.html --- 

Правильный YAML, имеет название, язык и внешний вместо автора.

 --- title: 'Stjerner og galakser' level: 2 logo: ../../assets/img/ccuk_logo.png license: '[Code Club World Limited Terms of Service](https://github.com/CodeClub/scratch-curriculum/blob/master/LICENSE.md)' translator: 'Ole Andreas Ramsdal' language: nb --- 

Неверный заголовок YAML, отсутствует автор.

    Вот один из способов сделать это. Я предполагаю, что у вас есть bash (для рекурсивного цикла по файлам), sed и awk. Вместо того, чтобы использовать bash, вы можете использовать find с -exec для поиска файлов.

    Общий stream:

    1. запросить у bash список *.md файлов, рекурсивно
    2. передать каждый файл в sed для извлечения заголовка YAML
    3. передать этот заголовок YAML в awk для проверки
    4. если заголовок не проходит проверку, выведите имя файла

    Сценарий:

     #!/bin/bash shopt -s globstar for file in **/*.md do # use sed for the header sed -n /^---$/,/^---$/p "$file" | awk ' BEGIN { good_title=0 good_lang=0 good_extaut=0 } /^title: .*/ { good_title=1 } /^language: [az][az]$/ { good_lang=1 } /^author: .*/ { good_extaut=1 } /^external: .*/ { good_extaut=1 } END { if (good_title && good_lang && good_extaut) exit 0 else exit 1 } ' \ || printf "Incorrect header found in %s\n" "$file" done 

    Вы можете легко настроить шаблоны сопоставления регулярных выражений в скрипте awk так, чтобы они были более строгими или более свободными, в зависимости от ваших точных требований (возможно, вам нужны буквенно-цифровые символы вместо «любой», как в текущем примере).

    Оператор sed извлекает заголовок YAML следующим образом:

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

    Скрипт awk немного перестроен, но я хотел изложить его для ясности. Каждый раз, когда вызывается awk, он устанавливает три флаговые переменные в ноль или в ложь. Если мы видим линии, которые соответствуют нашим критериям, мы устанавливаем соответствующий флаг в один / true. Как только все строки будут просмотрены, мы возвращаем успех или неудачу в зависимости от состояния этих флагов – все они должны быть истинными, чтобы «пройти» проверку.

    С этими соответствующими примерами файлов, разбросанными по текущему каталогу и подкаталогу:

     $ tree . . ├── bad1.md ├── good1.md ├── good2.md └── subdir ├── bad1.md └── good1.md 1 directory, 5 files 

    … скрипт выводит:

     Incorrect header found in bad1.md Incorrect header found in subdir/bad1.md