example - bash script execute command
Shell/Bash Command para obtener la enésima línea de STDOUT (13)
¿Hay algún comando bash que te permita obtener la enésima línea de STDOUT?
Es decir, algo que tomaría esto
$ ls -l
-rw-r--r--@ 1 root wheel my.txt
-rw-r--r--@ 1 root wheel files.txt
-rw-r--r--@ 1 root wheel here.txt
y haz algo como
$ ls -l | magic-command 2
-rw-r--r--@ 1 root wheel files.txt
Me doy cuenta de que esto sería una mala práctica al escribir scripts destinados a ser reutilizados, PERO cuando trabaje con el shell día a día sería útil para mí poder filtrar mi STDOUT de esa manera.
También me doy cuenta de que esto sería un comando semi-trivial para escribir (buffer STDOUT, devolver una línea específica), pero quiero saber si hay algún comando de shell estándar para hacer esto que estaría disponible sin que yo coloque un script en su lugar.
¿Perl está fácilmente disponible para ti?
$ perl -n -e ''if ($. == 7) { print; exit(0); }''
Obviamente, sustituye el número que quieras por 7.
Agregué esto en mi .bash_profile
function gdf(){
DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk ''{print $4}'')
SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk ''{print $2}'')
git show $SHA -- $DELETE_FILE_PATH
}
Y es obras
gdf <file name>
Alternativa a la buena forma de cabeza / cola:
ls -al | awk ''NR==2''
o
ls -al | sed -n ''2p''
En aras de la exhaustividad ;-)
código más corto
find / | awk NR==3
vida más corta
find / | awk ''NR==3 {print $0; exit}''
Hmm
sed no funcionó en mi caso. Propongo:
para líneas "impares" 1,3,5,7 ... ls | awk ''0 == (NR + 1)% 2''
para líneas "pares" 2,4,6,8 ls | awk ''0 == (NR)% 2''
Otro póster sugerido
ls -l | head -2 | tail -1
pero si canalizas la cabeza hacia la cola, parece que todo hasta la línea N se procesa dos veces.
Tubería de cola en la cabeza
ls -l | tail -n +2 | head -n1
sería más eficiente?
Para mayor completud ...
ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)
Tira las líneas hasta llegar al segundo, luego imprime la primera línea después de eso. Entonces, imprime la tercera línea.
Si es solo la segunda línea ...
ls -l | (read; head -n1)
Pon tantas ''lecturas como sea necesario.
Prueba esta versión sed
:
ls -l | sed ''2 ! d''
Dice "eliminar todas las líneas que no son la segunda".
Puedes usar awk:
ls -l | awk ''NR==2''
Actualizar
El código anterior no obtendrá lo que queremos debido a un error "uno por uno": la primera línea del comando ls -l es la línea total . Para eso, el siguiente código revisado funcionará:
ls -l | awk ''NR==3''
Sí, la forma más eficiente (como ya señaló Jonathan Leffler) es utilizar sed con print & quit:
set -o pipefail # cf. help set
time -p ls -l | sed -n -e ''2{p;q;}'' # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}" # cf. man bash | less -p ''PIPESTATUS''
Usando sed
, solo por variedad:
ls -l | sed -n 2p
El uso de esta alternativa, que parece más eficiente ya que deja de leer la entrada cuando se imprime la línea requerida, puede generar un SIGPIPE en el proceso de alimentación, que a su vez puede generar un mensaje de error no deseado:
ls -l | sed -n -e ''2{p;q}''
Lo he visto con suficiente frecuencia como para usar el primero (que es más fácil de escribir, de todos modos), aunque ls
no es un comando que se queja cuando se convierte en SIGPIPE.
Para una variedad de líneas:
ls -l | sed -n 2,4p
Para varios rangos de líneas:
ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e ''2,4p;20,30p''
ls -l | head -2 | tail -1