Como obter a primeira linha de um arquivo em um script bash?

249

Eu tenho que colocar em uma variável bash a primeira linha de um arquivo. Eu acho que é com o comando grep, mas é alguma maneira de restringir o número de linhas?

Neuquino
fonte

Respostas:

396

headpega as primeiras linhas de um arquivo e o -nparâmetro pode ser usado para especificar quantas linhas devem ser extraídas:

line=$(head -n 1 filename)
sth
fonte
3
Significativamente mais sobrecarga do que a readabordagem. $()garfos fora de um subnível, e usando um comando externo ( qualquer comando externo) significa que você está chamando execve(), invocando o vinculador e carregador (se ele está usando bibliotecas compartilhadas, que é geralmente o caso), etc.
Charles Duffy
2
Poderia ser ainda mais curto:line="$(head -1 FILENAME)"
nikolay
3
E também:line=`head -1 FILENAME`
Shai Alon
As reticências ao redor da head...abertura são um subconjunto, $()assim como ?.
Jaime Hablutzel
@JaimeHablutzel Sim, eles são a mesma coisa, embora eu pessoalmente ache que a $()sintaxe é mais fácil de ver e valorize a clareza sobre a concisão absoluta. gnu.org/software/bash/manual/html_node/…
Joseph Sikorski
61

Para ler a primeira linha usando o bash, use readstatement. por exemplo

read -r firstline<file

firstline será sua variável (não é necessário atribuir a outra)

ghostdog74
fonte
1
@ absorin, cat ... | read VARfalhará na maioria dos shells (todos, exceto zshaté onde eu sei), porque cada um dos componentes em um tubo será executado em subshells separados. O significado que $VARserá definido no subshell (que deixa de existir assim que o pipeline terminar de executar), e não no shell de chamada. Você pode contornar isso com read VAR <<EOF\n$(cat ...)\nEOF(onde cada \numa é uma nova linha).
Zrajm 28/03
@sorin, caté pura sobrecarga; muito mais eficiente do read -r var <fileque de cat file | readqualquer maneira, mesmo que o último não tenha falhado pelos motivos descritos no BashFAQ # 24 .
Charles Duffy
... se você estiver executando algo mais envolvido do que cat, em seguida,read -r var < <(otherprog ...)
Charles Duffy
14

Isso é suficiente e armazena a primeira linha de filenamena variável $line:

read -r line < filename

Eu também gosto awkdisso:

awk 'NR==1 {print; exit}' file

Para armazenar a própria linha, use a var=$(command)sintaxe. Nesse caso line=$(awk 'NR==1 {print; exit}' file),.

Ou até sed:

sed -n '1p' file

Com o equivalente line=$(sed -n '1p' file).


Veja um exemplo quando alimentamos readcom seq 10, ou seja, uma sequência de números de 1 a 10:

$ read -r line < <(seq 10) 
$ echo "$line"
1

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1
fedorqui 'Então pare de prejudicar'
fonte
1
sed '1!d;q'(ou sed -n '1p;q') imitará sua awklógica e impedirá a leitura adicional no arquivo. Como queremos apenas a primeira linha, podemos enganar alternativamente com sed qou awk '1;{exit}'ou até grep -m1 ^(menos código, a mesma lógica essencial). (Isto não é uma resposta ao inquérito downvote.)
Adam Katz
@AdamKatz, é um conjunto muito bom de maneiras, obrigado! Acho o que é grepmuito inteligente. É claro que também podemos dizer head -n 1 file.
fedorqui 'ASSIM, pare de prejudicar'
Sim, head -n1será mais rápido (binário menor para carregar) e readserá mais rápido (não há carregamento binário, isso é incorporado). Eu gosto especialmente grep -m1 --color .quando estou imprimindo a primeira linha, porque ela também será colorida, tornando-a excelente para títulos de tabelas.
Adam Katz
12
line=$(head -1 file)

Vai funcionar bem. (Como resposta anterior). Mas

line=$(read -r FIRSTLINE < filename)

será marginalmente mais rápido, como readé um comando interno do bash.

jackbot
fonte
21
O segundo método não funciona como está escrito, porque readnão imprime nada (então lineacaba em branco) e também é executado em um subshell (então FIRSTLINEé definido como a primeira linha, mas apenas no subshell, para que não esteja disponível posteriormente). Solução: useread -r line <filename
Gordon Davisson
5

Apenas echoa primeira lista do seu arquivo de origem no seu arquivo de destino.

echo $(head -n 1 source.txt) > target.txt
openwonk
fonte
3
Para qual head -n 1 source.txt > target.txtrealizará exatamente o mesmo.
YoYo
4

A pergunta não perguntou qual é a mais rápida, mas para adicionar à resposta sed, -n '1p' está com um desempenho ruim, pois o espaço do padrão ainda é verificado em arquivos grandes. Por curiosidade, descobri que a 'cabeça' ganha sobre sed por pouco:

# best:
head -n1 $bigfile >/dev/null

# a bit slower than head (I saw about 10% difference):
sed '1q' $bigfile >/dev/null

# VERY slow:
sed -n '1p' $bigfile >/dev/null
Neil McGill
fonte