Ottieni un elemento della stringa del percorso usando bash


9

Ho un file ASCII contenente percorsi di file che ho letto eseguendo:

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

Il file contiene percorsi di file con il seguente modello:

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

Come posso ottenere una parte specifica della stringa del percorso (da /a /), ad esempio ho bisogno di ottenere un output che stampa:

first
second
third

e anche

example1
example1
example2

Sono sicuro che esiste un modo per farlo usando espressioni regolari e sed, ma non ne ho familiarità.

Risposte:


17

Utilizzare 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

L' -d/imposta il delimitatore di colonna per /e -f2seleziona la seconda colonna.

Naturalmente puoi anche usare le variabili Bash invece di un nome file o dati pipe nel cutcomando:

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

Usando | cut -d/ -f3 in una pipa ha fatto il trucco. Grazie! Questo è il comando completo ora: while read p; do echo $p; done < filelist.txt | cut -d/ -f3
mcExchange

3
@mcExchange Non c'è motivo di usarlo while loop. È molto più semplice da fare cut -d/ -f3 filelist.txt
Monty Harder

1
Inoltre, evitare il tempo evita problemi di quotazione e non fallirà con le nuove righe nei nomi dei file.
Volker Siegel,

10

Potresti farlo direttamente nel tuo readcomando, usando la IFSvariabile es

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

5

Puoi usare 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

Se vogliamo qualsiasi elemento del percorso, è meglio usare qualcosa che può spezzare una stringa in campi, come ad esempio , ,, o . Però, può anche fare il lavoro con la sostituzione dei parametri, usando la sostituzione del modello e gettando tutto in un array.

$> 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

Ora abbiamo una serie di oggetti fatti fuori dal percorso. Si noti che se il percorso contiene spazi, può comportare l'alterazione del separatore di campo interno IFS.


1

Bash e cutsono la strada da percorrere, tuttavia un'alternativa usando Perl:

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

per il secondo /campo delimitato e

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

per il terzo /campo delimitato.

  • -l: abilita l'elaborazione automatica della fine della linea. Ha due effetti separati. Innanzitutto, chomps $ / (il separatore del record di input) automaticamente se usato con -n o -p. In secondo luogo, assegna $ \ (il separatore del record di output) per avere il valore di ottnum in modo che tutte le istruzioni di stampa abbiano quel separatore aggiunto di nuovo. Se l'ottetto viene omesso, imposta $ \ sul valore corrente di $ /.
  • -a: attiva la modalità autosplit quando usato con an o -p. Un comando di divisione implicita nell'array @F viene eseguito come prima cosa all'interno del ciclo while implicito prodotto da -n o -p.
  • -n: fa sì che Perl assuma il seguente ciclo attorno al programma, il che lo fa scorrere su argomenti di file un po 'come sed -n o awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
  • -e: può essere utilizzato per inserire una riga di programma;

  • print(@F[N]): stampa l'ennesimo 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.