Estoy tratando de obtener una línea específica de un archivo de texto.
Hasta ahora, en línea solo he visto cosas como sed, (solo puedo usar sh -not bash o sed ni nada por el estilo). Necesito hacer esto solo usando un script de shell básico.
cat file | while read line
do
#do something
done
Sé cómo iterar a través de las líneas, como se muestra arriba, pero ¿qué pasa si solo necesito obtener el contenido de una línea en particular?
cat
bien perosed
no? Eso no tiene sentido.cat
. ¡Oh ... lindocat
!Respuestas:
sed:
awk:
fuente
5!d
significa eliminar todas las líneas excepto 5. shell var es posible, necesita comillas dobles.sed -n 5p
esto parece más lógico de recordar para los principiantes, porque-n
significa "sin salida por defecto" yp
significa "imprimir", y no hay una mención potencialmente confusa de eliminar (cuando la gente habla de archivos, eliminar líneas tiende a significa algo diferente).-n '5p'
funciona para este problema. La diferencia aquí es5!d
que puede agregar-i
para volver a escribir el cambio en el archivo. sin embargo,-n 5p
tengo quesed -n '5p' f > f2&& mv f2 f
volver a hacerlo , para esta pregunta, estoy de acuerdo con su opinión.Suponiendo que
line
es una variable que contiene su número de línea requerido, si puede usarhead
ytail
, entonces es bastante simple:Si no, esto debería funcionar:
fuente
-eq
comparación es para enteros, por lo que quiere un número de línea, no contenido de línea ($line
). Esto debe solucionarse definiendo, por ejemplo,want=5
antes del bucle y luego utilizando la-eq
comparación en$want
. [movido de una edición rechazada]Podrías usar
sed -n 5p file
.También puede obtener un rango, por ejemplo,
sed -n 5,10p file
.fuente
Mejor método de rendimiento
Porque
sed
deja de leer cualquier línea después de la quinta.Actualizar el experimento del Sr. Roger Dueck
fuente
sed -n 5q
sed
deja de leer las líneas después de la quinta.sed -n 1p /usr/share/dict/words
ysed '1q;d' /usr/share/dict/words
utilizando eltime
comando; el primero tomó 0.043s, el segundo solo 0.002s, por lo que usar 'q' es definitivamente una mejora del rendimiento.Si, por ejemplo, desea obtener las líneas 10 a 20 de un archivo, puede utilizar cada uno de estos dos métodos:
o
p
en el comando anterior significa impresión.Esto es lo que verá:
fuente
La forma estándar de hacer este tipo de cosas es utilizar herramientas externas. No permitir el uso de herramientas externas mientras se escribe un script de shell es absurdo. Sin embargo, si realmente no desea utilizar herramientas externas, puede imprimir la línea 5 con:
Tenga en cuenta que esto imprimirá la línea lógica 5. Es decir, si
input-file
contiene continuaciones de línea, se contarán como una sola línea. Puede cambiar este comportamiento agregando-r
al comando de lectura. (Que es probablemente el comportamiento deseado).fuente
$((++i))
parece ser un bashismo; si el OP está restringido en el uso de herramientas externas, no asumiría que tendrán acceso a más de un simple/bin/sh
++
incrementos está específicamente marcado como opcional).$((i+=1))
funciona en Dash también.$(($i+1))
es la solución simple en la que estaba pensando.En paralelo con la respuesta de William Pursell , aquí hay una construcción simple que debería funcionar incluso en el shell Bourne v7 original (y, por lo tanto, también en lugares donde Bash no está disponible).
Nótese también la optimización para
break
salir del ciclo cuando hemos obtenido la línea que estábamos buscando.fuente
No me gustó particularmente ninguna de las respuestas.
Así es como lo hice.
fuente
¡Fácil con perl! Si desea obtener las líneas 1, 3 y 5 de un archivo, diga / etc / passwd:
fuente
seq 5 | perl -ne 'print if $. ~~ [1, 4, 5]'
pero smartmatch es experimental y se desaconseja su usofuente
sed -n 5p
que, por supuesto, aún se puede optimizar a algo comosed -n '5!d;p;q'