Como escolher arquivos em uma pasta na qual o cabeçalho contém um texto específico?

1

Caso de uso: digamos que há uma pasta cheia de grandes arquivos RDF + XML e eles seguem namespaces diferentes. Queremos encontrar os arquivos que seguem um determinado namespace (por exemplo, xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#" ).

A verificação de arquivos de cima para baixo consome tempo, pois um namespace é sempre definido nas primeiras linhas de um arquivo XML.

Como escolher arquivos em uma pasta enorme em que o cabeçalho contém um texto específico?

    
por Kristo Aun 25.11.2014 / 14:52

3 respostas

1

A resposta é algo assim:

 awk '/hi/ { if (FNR >= 5) { nextfile }; print FNR, FILENAME }' *

Altere o /hi/ com sua string de correspondência regex. Altere o 5 para ser o último número da linha no cabeçalho que você deseja ver.

    
por 25.11.2014 / 15:15
1

Para procurar apenas nas primeiras 5 linhas, se o seu awk suportar nextfile :

TEXT='xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"' \
  find . -type f -exec awk '
     index($0, ENVIRON["TEXT"]) {print FILENAME; nextfile}
     FNR == 5 {nextfile}' {} +

(se o seu awk não suportar nextfile , isso será silenciosamente ignorado e os arquivos serão totalmente lidos).

Ou você pode usar perl :

TEXT='xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"' \
  find . -type f -exec perl -Tne '
     if (index($_, $ENV{"TEXT"}) >= 0) {print "$ARGV\n"; close ARGV}
     elsif ($. == 5) {close ARGV}' {} +
    
por 25.11.2014 / 17:24
1

Se todos os seus arquivos tiverem uma declaração de namespace, com o GNU / FreeBSD / OSX grep ou qualquer implementação que tenha a opção -m , você pode procurar a declaração de namespace e sair assim que for encontrada, em seguida canalizar o resultado um segundo grep para obter o namespace em que você está interessado.

grep -m xmlns: *.xml  |grep 'xmlns:crm="http://www.cidoc-crm.org/cidoc-crm#"'

Se alguns arquivos não tiverem uma declaração de namespace reconhecível ou algum outro padrão que diga “quit”, use sed ou awk para especificar uma condição de desistência com base no número da linha. Com o sed, não há como contabilizar as linhas por arquivo, portanto, é necessário invocar o sed em cada arquivo:

for x in *.xml; do
  if [ -n "$(sed -n -e 's/.*xmlns:crm="http:\/\/www.cidoc-crm.org\/cidoc-crm#".*/1/' -e '/xmlns:/q' -e '5q')" ]; then
    printf '%s\n' "$x"
  fi
done

Veja a resposta de Stéphane Chazelas para uma solução awk.

Qualquer método baseado em ferramentas de processamento de texto é inerentemente frágil . Por exemplo, ele pegaria uma declaração de namespace comentada. A menos que você revise os resultados manualmente ou saiba que todos os seus arquivos têm uma estrutura “domesticada” (sem comentários, nenhum texto de carga útil semelhante ao que você está pesquisando, etc.), você deve usar um analisador de XML adequado em vez disso - mas será mais lento.

    
por 26.11.2014 / 02:10

Tags