¿Cómo obtener la primera línea de un archivo en un script bash?

249

Tengo que poner en una variable bash la primera línea de un archivo. Supongo que es con el comando grep, pero ¿hay alguna forma de restringir el número de líneas?

Neuquino
fuente

Respuestas:

396

headtoma las primeras líneas de un archivo y el -nparámetro se puede usar para especificar cuántas líneas se deben extraer:

line=$(head -n 1 filename)
algo
fuente
3
Significativamente más gastos generales que el readenfoque. $()bifurca un subnivel, y utilizando un comando externo ( cualquier comando externo) significa que está llamando execve(), invocando el enlazador y el cargador (si se trata de utilizar las bibliotecas compartidas, que suele ser el caso), etc.
Charles Duffy
2
Podría ser aún más corto:line="$(head -1 FILENAME)"
nikolay
3
Y también:line=`head -1 FILENAME`
Shai Alon
¿Los backticks alrededor de head...abrir una subshell como lo $()hace?
Jaime Hablutzel
@JaimeHablutzel Sí, son lo mismo, aunque personalmente considero que la $()sintaxis es más fácil de ver y valoro la claridad en lugar de la absoluta terquedad. gnu.org/software/bash/manual/html_node/…
Joseph Sikorski
61

para leer la primera línea usando bash, use la readdeclaración. p.ej

read -r firstline<file

firstline será tu variable (No es necesario asignarla a otra)

ghostdog74
fuente
1
@sorin, cat ... | read VARfallará en la mayoría de los shells (todos excepto zshhasta donde yo sé) porque cada uno de los componentes de una tubería se ejecutará en subshells separados. Lo que significa que $VARse establecerá en el subshell (que dejará de existir tan pronto como la canalización haya terminado de ejecutarse) en lugar de en el shell de invocación. Puede evitar esto con read VAR <<EOF\n$(cat ...)\nEOF(donde cada uno \nes una nueva línea).
zrajm
@sorin, cates pura sobrecarga; mucho más eficiente que read -r var <filede cat file | readtodos modos, incluso si este último no falla por las razones descritas en BashFAQ # 24 .
Charles Duffy el
... si estás ejecutando algo más complicado que cat, entoncesread -r var < <(otherprog ...)
Charles Duffy
14

Esto es suficiente y almacena la primera línea de filenameen la variable $line:

read -r line < filename

También me gusta awkpara esto:

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

Para almacenar la línea en sí, use la var=$(command)sintaxis. En este caso line=$(awk 'NR==1 {print; exit}' file),.

O incluso sed:

sed -n '1p' file

Con el equivalente line=$(sed -n '1p' file).


Vea una muestra cuando alimentamos readcon seq 10, es decir, una secuencia de números del 1 al 10:

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

$ line=$(awk 'NR==1 {print; exit}' <(seq 10))
$ echo "$line"
1
fedorqui 'así que deja de dañar'
fuente
1
sed '1!d;q'(o sed -n '1p;q') imitará su awklógica y evitará leer más en el archivo. Debido a que sólo queremos la primera línea, podemos engañar, alternativamente, con sed qo awk '1;{exit}'ni siquiera grep -m1 ^(menos código, la misma lógica esencial). (Esta no es una respuesta a la consulta de voto negativo.)
Adam Katz
@AdamKatz es un muy buen conjunto de formas, ¡gracias! Encuentro uno con grepmuy inteligente. Por supuesto, también podemos decir head -n 1 file.
Fedorqui 'así que deja de dañar'
Sí, head -n1será más rápido (binario más pequeño para cargar) y readserá más rápido (sin binario para cargar, eso es algo incorporado). Me gusta especialmente grep -m1 --color .cuando solo estoy imprimiendo la primera línea porque también coloreará la línea, por lo que es ideal para los encabezados de las tablas.
Adam Katz
12
line=$(head -1 file)

Funcionará bien (Como respuesta anterior). Pero

line=$(read -r FIRSTLINE < filename)

será marginalmente más rápido como lo reades un comando bash incorporado.

Jackbot
fuente
21
El segundo método no funciona como está escrito, porque readno imprime nada (por lo que linetermina en blanco), y también se ejecuta en una subshell (por lo que FIRSTLINEse establece en la primera línea, pero solo en la subshell, por lo que no está disponible después). Solución: solo useread -r line <filename
Gordon Davisson
5

Solo echola primera lista de su archivo fuente en su archivo de destino.

echo $(head -n 1 source.txt) > target.txt
openwonk
fuente
3
Para lo cual se head -n 1 source.txt > target.txtlogrará exactamente lo mismo.
YoYo
4

La pregunta no pregunta cuál es la más rápida, pero para agregar a la respuesta sed, -n '1p' está funcionando mal ya que el espacio del patrón todavía se escanea en archivos grandes. Por curiosidad descubrí que 'head' gana a sed por poco:

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