AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 457273
Accepted
Øistein Søvik
Øistein Søvik
Asked: 2018-07-20 10:03:19 +0800 CST2018-07-20 10:03:19 +0800 CST 2018-07-20 10:03:19 +0800 CST

Encontrando cabeçalhos YAML incorretos

  • 772

Estou tentando identificar quais arquivos no meu projeto têm cabeçalhos incorretos. Todos os arquivos começam assim

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

Onde . . . representa apenas mais cabeçalhos. Os cabeçalhos não contém recuo. Usando a seguinte expressão, consegui extrair o cabeçalho YAML de todos os arquivos.

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

Agora quero listar os cabeçalhos YAML incorretos.

  • Cada cabeçalho YAML deve ter umtitle: some text
  • Todo cabeçalho YAML deve terlanguage: [a-z]{2}
  • Deve conter um external: .*ou author: .*.
  • A colocação de title:, level:, external:e language:varia.

Eu tentei fazer algo como

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

No entanto, o problema com isso é que ele pesquisa o arquivo inteiro, não apenas o cabeçalho YAML. Então, acho que resolver os problemas acima se resume a como posso alimentar o resultado do cabeçalho YAML da minha pesquisa anterior no grep novamente. eu tentei

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

No entanto, isso me deu um erro "Nenhum arquivo ou diretório", então estou um pouco incerto sobre como proceder.

Exemplos:

---
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
---

Correto YAML, tem autor, idioma e título.

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

YAML correto, tem título, idioma e externo em vez de autor.

---
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
---

Cabeçalho YAML incorreto, autor ausente.

grep yaml
  • 2 2 respostas
  • 322 Views

2 respostas

  • Voted
  1. Best Answer
    Jeff Schaller
    2018-07-21T13:28:16+08:002018-07-21T13:28:16+08:00

    Aqui está uma maneira de fazer isso. Suponho que você tenha bash (para percorrer recursivamente os arquivos), sed e awk. Em vez de usar o bash, você pode usar findcomo alternativa -execpara procurar os arquivos.

    O fluxo geral é:

    1. peça ao bash a lista de *.mdarquivos, recursivamente
    2. passe cada arquivo sedpara extrair o cabeçalho YAML
    3. passe esse cabeçalho YAML para awk para validação
    4. se o cabeçalho falhar na validação, imprima o nome do arquivo

    O roteiro:

    #!/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: [a-z][a-z]$/ { 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
    

    Você pode facilmente ajustar os padrões de correspondência regex no script awk para serem mais rígidos ou mais flexíveis, dependendo de seus requisitos exatos (talvez você queira caracteres alfanuméricos em vez de "qualquer", como o atual .em seu exemplo).

    A sedinstrução extrai o cabeçalho YAML por:

    • suprimindo a impressão padrão ( -n)
    • solicitando uma linha de endereços que correspondam ao padrão: início de linha, ---, fim de linha; o segundo padrão deve ocorrer após o primeiro padrão.
    • esse intervalo de endereços é então pgravado

    O awkroteiro é um pouco exagerado, mas eu queria soletrá-lo para maior clareza. Cada vez que o awk é chamado, ele define três variáveis ​​de flag para zero ou false. Se virmos linhas que correspondem aos nossos critérios, definimos o sinalizador correspondente como um/verdadeiro. Depois que todas as linhas forem vistas, retornamos sucesso ou falha com base no status desses sinalizadores - todos eles devem ser verdadeiros para "passar" na validação.

    Com esses arquivos de amostra com nomes apropriados espalhados no diretório atual e em um subdiretório:

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

    ... as saídas do script:

    Incorrect header found in bad1.md
    Incorrect header found in subdir/bad1.md
    
    • 2
  2. Kusalananda
    2022-08-28T11:11:42+08:002022-08-28T11:11:42+08:00

    Para extrair o cabeçalho de um arquivo, podemos usar sedassim:

    sed -e '1,/^---$/!d' -e '/^---$/d' filename
    

    Isso remove tudo do arquivo, exceto as linhas entre a linha 1 e a próxima linha que é exatamente ---. A segunda expressão também exclui todas as ---linhas dos dados para que você fique apenas com o cabeçalho YAML.

    yqUsarei o utilitário baseado em Python de Andrey Kislyuk . Como este é um wrapper útil em torno do versátil analisador JSON jq, podemos detectar facilmente se os valores correspondentes às chaves são null, non- nullou uma string específica etc.

    Na jqsintaxe, podemos testar se uma chave, keyname, existe em um objeto com has("keyname"). Também podemos testar se o valor de uma chave corresponde a uma expressão regular específica, RE, usando .keyname | test("RE").

    Os testes mencionados na pergunta podem ser traduzidos na seguinte jqexpressão:

    has("title")            and
    (.title | test("."))    and
    has("language")         and
    (.language | test("[a-z]{2}"))  and
    (has("external") or has("author"))
    

    ou, mais curto, mas menos expressivo,

    (.title? != null) and
    (.language? | test("[a-z]{2}")) and
    (has("external") or has("author"))
    

    Isso garante que cada chave exista e que os valores para as chaves que precisam ter nullvalores diferentes estejam corretos.

    Executando isso nos três arquivos de exemplo, com nossos testes no arquivo de script validate:

    $ sed -e '1,/^---$/!d' -e '/^---$/d' file1.md | yq -f validate
    true
    $ sed -e '1,/^---$/!d' -e '/^---$/d' file2.md | yq -f validate
    true
    $ sed -e '1,/^---$/!d' -e '/^---$/d' file3.md | yq -f validate
    false
    

    Podemos generalizar isso para testar todos os .mdarquivos no diretório atual ou abaixo usando findassim:

    find . -name '*.md' -type f -exec sh -c '
        for pathname do
            if ! sed -e "1,/^---\$/!d" -e "/^---\$/d" "$pathname" |
                 yq -e -f validate >/dev/null
            then
                printf "Invalid YAML header: %s\n" "$pathname"
            fi
        done' sh {} +
    

    ou, com qualquer shell que suporte o **padrão globbing (habilitado com shopt -s globstarin bash):

    for pathname in ./**/*.md
    do
        if ! sed -e '1,/^---$/!d' -e '/^---$/d' "$pathname" |
             yq -e -f validate >/dev/null
        then
            printf 'Invalid YAML header: %s\n' "$pathname"
        fi
    done
    

    Aqui, também descartamos a saída yqe, em vez disso, usamos a ferramenta com sua -eopção. Isso faz com que o status de saída do utilitário reflita o valor da última expressão avaliada, ou seja, zero para true e diferente de zero para false neste caso. Isso facilita o uso do nosso pipeline sed+ yqdiretamente em uma ifdeclaração.

    Executando isso com nossos três arquivos de teste, obtemos

    Invalid YAML header: ./file3.md
    
    • 0

relate perguntas

  • resultados inesperados de `service | grep`

  • Leia o arquivo de texto com palavras e sua contagem de ocorrências e saída de impressão classificada

  • Comando ls | grep mostrando apenas diretórios (quando também deveria mostrar arquivos)

  • quando o grep conta e quando não

  • grep --line-buffered até X linhas?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve