Obtenga un elemento de la cadena de ruta usando bash


9

Tengo un archivo ASCII que contiene rutas de archivos que leí ejecutando:

while read p; do echo $p; done < filelist.txt

El archivo contiene rutas de archivo con el siguiente patrón:

./first/example1/path
./second/example1/path
./third/example2/path

¿Cómo puedo obtener una parte específica de la cadena de ruta (de /a /), por ejemplo, necesito obtener una salida que imprima:

first
second
third

y también

example1
example1
example2

Estoy seguro de que hay una manera de hacerlo usando expresiones regulares y sed, pero no estoy familiarizado con eso.

Respuestas:


17

Uso cut:

$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

$ cut -d/ -f2 filelist.txt 
first
second
third

$ cut -d/ -f3 filelist.txt 
example1
example1
example2

El -d/establece el delimitador de columnas a /y los -f2selecciona la segunda columna.

Por supuesto, también puede usar variables Bash en lugar de un nombre de archivo o datos de canalización en el cutcomando:

cut -d/ -f3 $MyVariable
echo ./another/example/path | cut -d/ -f3

Usar | cut -d/ -f3 en una tubería hizo el truco. ¡Gracias! Este es el comando completo ahora: while read p; do echo $p; done < filelist.txt | cut -d/ -f3
mcExchange

3
@mcExchange No hay razón para usar ese ciclo while. Es mucho más simple hacerlo cut -d/ -f3 filelist.txt
Monty Harder

1
Además, evitar el tiempo evita los problemas de citas y no fallará con las nuevas líneas en los nombres de archivo.
Volker Siegel

10

Puede hacerlo directamente en su readcomando, usando la IFSvariable eg

$ while IFS=/ read -r p1 p2 p3 r; do echo "$p2"; done < filelist.txt 
first
second
third

5

Puedes usar awk

pilot6@Pilot6:~$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

pilot6@Pilot6:~$ awk -F "/" '{print $2}' filelist.txt
first
second
third

pilot6@Pilot6:~$ awk -F "/" '{print $3}' filelist.txt
example1
example1
example2

3

Si queremos algún elemento de la ruta, es mejor usar algo que pueda dividir una cadena en campos, como , ,o . Sin embargo, También puede hacer el trabajo con la sustitución de parámetros, utilizando el reemplazo de patrones y arrojando todo en una matriz.

$> echo ${FILE//\//\ }                                                         
sys class backlight intel_backlight brightness
$> ARRAY=( ${FILE//\//" " } )                                                  
$> echo ${ARRAY[2]}
backlight

$> FILE="./dir1/dir2/file.txt"                                                 
$> ARRAY=( ${FILE//\/" "} )
$> echo ${ARRAY[@]}                                                            
. dir1 dir2 file.txt
$> echo ${ARRAY[1]}
dir1

Ahora tenemos una variedad de artículos hechos fuera del camino. Tenga en cuenta que si la ruta contiene espacios, puede implicar la alteración del separador de campo interno IFS.


1

Bash y cutson el camino a seguir, sin embargo, una alternativa con Perl:

perl -F/ -lane 'print(@F[1])' filelist.txt

para el segundo /campo delimitado y

perl -F/ -lane 'print(@F[2])' filelist.txt

para el tercer /campo delimitado.

  • -l: habilita el procesamiento automático de final de línea. Tiene dos efectos separados. Primero, automáticamente divide $ / (el separador de registro de entrada) cuando se usa con -n o -p. En segundo lugar, asigna $ \ (el separador de registro de salida) para que tenga el valor de octnum, de modo que cualquier declaración de impresión tendrá ese separador agregado nuevamente. Si se omite octnum, establece $ \ en el valor actual de $ /.
  • -a: activa el modo de división automática cuando se usa con -n o -p. Un comando de división implícito para la matriz @F se realiza como lo primero dentro del bucle while implícito producido por -n o -p.
  • -n: hace que Perl asuma el siguiente ciclo alrededor de su programa, lo que lo hace iterar sobre argumentos de nombre de archivo algo así como sed -n o awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e: puede usarse para ingresar una línea de programa;

  • print(@F[N]): imprime el enésimo campo.
% cat filelist.txt 
./first/example1/path
./second/example1/path
./third/example2/path
% perl -F/ -lane 'print(@F[1])' filelist.txt
first
second
third
% perl -F/ -lane 'print(@F[2])' filelist.txt
example1
example1
example2
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.