Obtener el último campo usando awk substr


99

Estoy tratando de usar awkpara obtener el nombre de un archivo dada la ruta absoluta al archivo.
Por ejemplo, cuando me dan la ruta de entrada que /home/parent/child/filenameme gustaría obtener, filename lo he intentado:

awk -F "/" '{print $5}' input

que funciona perfectamente.
Sin embargo, estoy codificando, lo $5cual sería incorrecto si mi entrada tiene la siguiente estructura:

/home/parent/child1/child2/filename

Entonces, una solución genérica requiere tomar siempre el último campo (que será el nombre del archivo).

¿Existe una forma sencilla de hacer esto con la función awk substr?


2
como alguien señaló, usar basenamees la forma oficial de hacer esto, usar awkpara esto no es bueno para decirlo a la ligera. : D
Kashyap

Respuestas:


206

Utilice el hecho de que awkdivide las líneas en los campos según un separador de campo, que puede definir. Por lo tanto, al definir el separador de campo /, puede decir:

awk -F "/" '{print $NF}' input

En cuanto NFal número de campos del registro actual, imprimir $NFsignifica imprimir el último.

Entonces, dado un archivo como este:

/home/parent/child1/child2/child3/filename
/home/parent/child1/child2/filename
/home/parent/child1/filename

Esta sería la salida:

$ awk -F"/" '{print $NF}' file
filename
filename
filename

3
Funciona perfectamente. No pensé en la variable $ NF. Gracias por su respuesta inmediata, sencilla y eficaz.
Mari

6
Para el penult one, use $(NF-1).
Itachi

1
Estaba escribiendo un script para trabajar con algunos comandos de la ventana acoplable y esto funcionó. ¡Gracias!
Harlin

30

En este caso, es mejor usar en basenamelugar de awk:

 $ basename /home/parent/child1/child2/filename
 filename

4
@Mari FYI dirname hace lo contrario y elimina el archivo, no la ruta.
Chris Seymour

5

Otra opción es utilizar la bash sustitución de parámetros .

$ foo="/home/parent/child/filename"
$ echo ${foo##*/}
filename
$ foo="/home/parent/child/child2/filename"
$ echo ${foo##*/}
filename

5

Si está abierto a una solución de Perl, aquí hay una similar a la solución awk de fedorqui:

perl -F/ -lane 'print $F[-1]' input

-F/especifica /que el separador de campo
$F[-1]es el último elemento de la @Fmatriz autosplit


1
Gracias. Esto me ayudó a conseguir el último campo. perl -F "/" -lane 'print $ F [-2]' input
riderchap

esto funcionó para mí al recibir de entrada canalizada. Me olvidé por completo de Perl.
Christopher

3

Debería ser un comentario a la respuesta del nombre de base, pero no tengo suficiente sentido.

Si no usa comillas dobles, basenameno funcionará con la ruta donde hay un carácter de espacio:

$ basename /home/foo/bar foo/bar.png
bar

ok con comillas ""

$ basename "/home/foo/bar foo/bar.png"
bar.png

ejemplo de archivo

$ cat a
/home/parent/child 1/child 2/child 3/filename1
/home/parent/child 1/child2/filename2
/home/parent/child1/filename3

$ while read b ; do basename "$b" ; done < a
filename1
filename2
filename3

3

Sé que estoy como 3 años tarde en esto, pero ... debería considerar la expansión de parámetros, está integrada y es más rápida.

si su entrada está en una var, digamos, $ var1, simplemente hágalo ${var1##*/}. Mira abajo

$ var1='/home/parent/child1/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/child3/filename'
$ echo ${var1##*/}
filename

2

Como 5 años tarde, lo sé, gracias por todas las propuestas, solía hacer esto de la siguiente manera:

$ echo /home/parent/child1/child2/filename | rev | cut -d '/' -f1 | rev
filename

Me alegra notar que hay mejores modales


-1

También puedes usar:

    sed -n 's/.*\/\([^\/]\{1,\}\)$/\1/p'

o

    sed -n 's/.*\/\([^\/]*\)$/\1/p'

1
En este punto, nadie votó a favor de esta respuesta, probablemente porque es comparablemente desagradable :)
Josip Rodin
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.