Holen Sie sich ein Element der Pfadzeichenfolge mit bash

9

Ich habe eine ASCII-Datei mit Dateipfaden, die ich durch Ausführen gelesen habe:

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

Die Datei enthält Dateipfade mit folgendem Muster:

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

Wie kann ich einen bestimmten Teil der Pfadzeichenfolge (von /bis /) abrufen, z. B. muss eine Ausgabe abgerufen werden, die Folgendes druckt:

first
second
third

und auch

example1
example1
example2

Ich bin mir sicher, dass es eine Möglichkeit gibt, dies mit regulären Ausdrücken zu tun sed, aber ich bin damit nicht vertraut.

mcExchange
quelle

Antworten:

17

Verwendung 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

Das -d/setzt den Spaltenbegrenzer auf /und -f2wählt die 2. Spalte aus.

Sie können natürlich auch Bash-Variablen anstelle eines Dateinamens oder Pipe-Daten in den cutBefehl verwenden:

cut -d/ -f3 $MyVariable
echo ./another/example/path | cut -d/ -f3
Byte Commander
quelle
Die Verwendung | cut -d/ -f3 in einem Rohr hat den Trick getan. Vielen Dank! Dies ist jetzt der vollständige Befehl: while read p; do echo $p; done < filelist.txt | cut -d/ -f3
mcExchange
3
@mcExchange Es gibt keinen Grund, diese while-Schleife zu verwenden. Es ist viel einfacher zu tun cut -d/ -f3 filelist.txt
Monty Harder
1
Durch das Vermeiden der Weile werden außerdem Probleme beim Zitieren vermieden, und bei Zeilenumbrüchen in Dateinamen schlägt dies nicht fehl.
Volker Siegel
10

Sie können dies direkt in Ihrem readBefehl tun , indem Sie die IFSVariable z

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

Sie können verwenden 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
Pilot6
quelle
3

Wenn Sie ein Element des Pfads möchten, verwenden Sie am besten etwas, das eine Zeichenfolge in Felder kann , z. B. , , oder . Allerdings tun kann , auch den Job mit dem Parameter Substitution, Muster Ersatz verwenden und alles in ein Array zu werfen.

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

Jetzt haben wir eine Reihe von Elementen aus dem Pfad. Wenn der Pfad Leerzeichen enthält, muss möglicherweise das interne Feldtrennzeichen geändert werden IFS.

Sergiy Kolodyazhnyy
quelle
1

Bash und cutsind der richtige Weg, jedoch eine Alternative mit Perl:

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

für das /zweitbegrenzte Feld und

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

für das /drittbegrenzte Feld.

  • -l: Aktiviert die automatische Zeilenendverarbeitung. Es hat zwei separate Effekte. Erstens wird bei Verwendung mit -n oder -p automatisch $ / (das Trennzeichen für Eingabedatensätze) geändert. Zweitens wird $ \ (das Trennzeichen für den Ausgabedatensatz) mit dem Wert octnum zugewiesen, sodass bei Druckanweisungen das Trennzeichen wieder hinzugefügt wird. Wenn octnum weggelassen wird, wird $ \ auf den aktuellen Wert von $ / gesetzt.
  • -a: Aktiviert den Autosplit-Modus, wenn er mit -n oder -p verwendet wird. Ein impliziter Split-Befehl für das @ F-Array wird als erstes in der impliziten while-Schleife ausgeführt, die von -n oder -p erzeugt wird.
  • -n: bewirkt, dass Perl die folgende Schleife um Ihr Programm annimmt, wodurch es über Dateinamenargumente wie sed -n oder awk iteriert:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
  • -e: kann verwendet werden, um eine Programmzeile einzugeben;

  • print(@F[N]): druckt das N-te Feld.
% 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
quelle