Como imprimir o conteúdo do arquivo apenas se a primeira linha corresponder a um determinado padrão?

11

Estou escrevendo um script, quero verificar se a primeira linha do arquivo corresponde a um determinado padrão e, se for o caso, imprima o arquivo. Como posso conseguir isso?

Como faço para verificar o padrão? Existe uma maneira de verificar o padrão e com base na saída fazer alguma coisa ..

EDITAR: Por favor, dê uma olhada nesta questão: link

Eu quero algo assim, mas nenhum deles funcionou para mim. Eu basicamente quero verificar se a primeira linha corresponde a um padrão regex ou não e com base nessa impressão as linhas do arquivo.

    
por Mathew 28.09.2015 / 21:39

5 respostas

17

Você pode fazer isso com ed :

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

o truque aqui é tentar substituir a linha PATTERN on 1st por si mesma. ed será eliminado se não puder encontrar o padrão especificado, portanto, ,p (imprimir arquivo inteiro) será executado apenas se 1s/PATTERN/&/ for bem-sucedido.

Ou com sed :

sed -n '1{
/PATTERN/!q
}
p' infile

este q uits se a primeira linha não ( ! ) corresponder a PATTERN , caso contrário, p solicitará todas as linhas.
Ou, como apontado por Toby Speight , com o GNU sed :

sed '1{/PATTERN/!Q}' infile

Q é o mesmo que q , mas não imprime o espaço do padrão.

    
por 28.09.2015 / 22:34
15

Com o POSIX tools chest:

{ head -n 1 | grep pattern && cat; } <file
    
por 29.09.2015 / 04:06
8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

imprime o nome dos arquivos txt não ocultos no diretório atual cuja primeira linha corresponde à expressão regular estendida pattern com as awk implementações que suportam nextfile .

Se, em vez de imprimir o nome do arquivo, você quiser imprimir todo o conteúdo do arquivo, você pode fazer:

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

Isso é eficiente, pois ele executa apenas um comando, mas awk não é o comando mais eficiente para despejar o conteúdo de um arquivo. Com arquivos grandes, você pode obter melhores desempenhos fazendo algo como:

 awk '/pattern/{printf "%s
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt
", FILENAME}; {nextfile}' ./*.txt | xargs -r0 cat

Ou seja, use apenas awk para imprimir a lista de arquivos correspondentes (delimitados por 0) e confie em cat para despejar seu conteúdo.

    
por 28.09.2015 / 21:47
6

Se você está escrevendo um script de shell, pode ser algo como

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

Ou, em Perl:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*
    
por 28.09.2015 / 23:55
5

Oldschool, apenas traduza sua frase em comandos padrão:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

Para aprender bash é um bom começo. Se você só precisa de uma solução rápida, tente as respostas sed, awk ou perl. Ambos bons, mas eles são próprios idiomas que você precisa (e provavelmente quer) para aprender.

É um exemplo bastante simples, então se você quiser aprender mais, você também pode tentar o mesmo em ruby, php, js (por exemplo, em nodejs) ou qualquer outra linguagem que permita o acesso a arquivos. Até C / C ++ ou Java devem ser fáceis de gerenciar com uma pequena tarefa.

    
por 29.09.2015 / 03:07