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.

mcExchange
fuente

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
Byte Commander
fuente
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
conductor de acero
fuente
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
Piloto6
fuente
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.

Sergiy Kolodyazhnyy
fuente
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
kos
fuente