Holen Sie sich das letzte Feld mit awk substr


99

Ich versuche zu verwenden awk, um den Namen einer Datei mit dem absoluten Pfad zur Datei zu erhalten.
Wenn /home/parent/child/filenameich beispielsweise den Eingabepfad angegeben habe, den ich erhalten möchte, habe filename ich Folgendes versucht:

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

das funktioniert perfekt.
Ich bin jedoch hart codiert, $5was falsch wäre, wenn meine Eingabe die folgende Struktur hätte:

/home/parent/child1/child2/filename

Für eine generische Lösung muss also immer das letzte Feld (der Dateiname) verwendet werden.

Gibt es eine einfache Möglichkeit, dies mit der awk substr-Funktion zu tun?


2
Wie jemand darauf hingewiesen hat, basenameist die Verwendung der offiziellen Methode, dies zu verwenden, awkist nicht gut, um es leicht auszudrücken. : D
Kashyap

Antworten:


206

Verwenden Sie die Tatsache, dass awkdie Linien in Felder basierend auf einem Feldtrennzeichen aufgeteilt werden, das Sie definieren können. Wenn /Sie also das Feldtrennzeichen definieren, können Sie sagen:

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

In NFBezug auf die Anzahl der Felder des aktuellen Datensatzes $NFbedeutet Drucken das Drucken des letzten.

Also gegeben eine Datei wie diese:

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

Dies wäre die Ausgabe:

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

3
Es funktioniert perfekt. Ich habe nicht an $ NF Variable gedacht. Vielen Dank für Ihre sofortige einfache und effektive Antwort.
Mari

6
Verwenden Sie für den vorletzten $(NF-1).
Itachi

1
Schrieb ein Skript, um mit einigen Docker-Befehlen zu arbeiten, und dies tat den Trick. Vielen Dank!
Harlin

30

In diesem Fall ist es besser zu verwenden basenameals awk:

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

4
@Mari FYI dirname macht das Gegenteil und streift Datei nicht den Pfad.
Chris Seymour

5

Eine andere Option ist die Verwendung der bash Parametersubstitution .

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

5

Wenn Sie offen für eine Perl-Lösung sind, finden Sie hier eine, die der awk-Lösung von fedorqui ähnelt:

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

-F/Spezifiziert /als Feldtrennzeichen
$F[-1]ist das letzte Element in dem @FAutosplit - Array


1
Vielen Dank. Dies hat mir geholfen, das vorletzte Feld zu erreichen. perl -F "/" -lane 'print $ F [-2]' input
riderchap

Dies funktionierte bei mir beim Empfang von leitungsgebundenen Daten. Perl total vergessen.
Christopher

3

Es sollte ein Kommentar zur Antwort auf den Basisnamen sein, aber ich habe nicht genug Sinn.

Wenn Sie keine doppelten Anführungszeichen verwenden, basenamefunktioniert dies nicht mit Pfaden, bei denen Leerzeichen vorhanden sind:

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

ok mit Anführungszeichen ""

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

Dateibeispiel

$ 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

Ich weiß, dass ich 3 Jahre zu spät dran bin, aber ... Sie sollten die Parametererweiterung in Betracht ziehen, sie ist eingebaut und schneller.

Wenn sich Ihre Eingabe in einer Variablen befindet, sagen wir einfach $ var1 ${var1##*/}. Schau unten

$ 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

Wie 5 Jahre zu spät, ich weiß, danke für all die Vorschläge, ich habe dies folgendermaßen gemacht:

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

Ich bin froh zu bemerken, dass es bessere Manieren gibt


-1

Sie können auch verwenden:

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

oder

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

1
Zu diesem Zeitpunkt hat niemand diese Antwort positiv bewertet, wahrscheinlich weil sie vergleichsweise flüchtig ist :)
Josip Rodin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.