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.
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?
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}' {} +
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.