Bei einem String-Dateipfad wie /foo/fizzbuzz.bar
wie würde ich die Bash verwenden, um nur die fizzbuzz
Teil der besagten Zeichenkette?
Antworten
Zu viele Anzeigen?Reiner Bash-Weg:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
Diese Funktionalität wird in man bash unter "Parameter Expansion" erklärt. Es gibt auch andere Möglichkeiten als Bash: awk, perl, sed und so weiter.
EDIT: Funktioniert mit Punkten in der Datei Suffixe und braucht das Suffix (die Erweiterung) nicht zu kennen, aber nicht Arbeit mit Punkten in der Name selbst.
Verwendung von basename
setzt voraus, dass Sie wissen, wie die Dateierweiterung lautet, nicht wahr?
Und ich glaube, dass die verschiedenen Vorschläge für reguläre Ausdrücke nicht mit einem Dateinamen zurechtkommen, der mehr als ein ".
Das Folgende scheint mit doppelten Punkten zurechtzukommen. Oh, und Dateinamen, die selbst ein "/" enthalten (nur so zum Spaß)
Um es mit den Worten Pascals zu sagen: "Tut mir leid, dass das Drehbuch so lang ist. Ich hatte keine Zeit, es kürzer zu machen.
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
Zusätzlich zu den POSIX-konforme Syntax verwendet in diese Antwort ,
basename string [suffix]
wie in
basename /foo/fizzbuzz.bar .bar
GNU basename
unterstützt eine andere Syntax:
basename -s .bar /foo/fizzbuzz.bar
mit demselben Ergebnis. Der Unterschied und Vorteil ist, dass -s
impliziert -a
, die mehrere Argumente unterstützt:
$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar
Dies kann sogar dateinamensicher gemacht werden, indem man die Ausgabe mit NUL-Bytes trennt und die -z
zum Beispiel für diese Dateien, die Leerzeichen, Zeilenumbrüche und globale Zeichen enthalten (in Anführungszeichen ls
):
$ ls has*
'has'$'\n''newline.bar' 'has space.bar' 'has*.bar'
Einlesen in ein Array:
$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")
readarray -d
erfordert Bash 4.4 oder eine neuere Version. Für ältere Versionen müssen wir eine Schleife machen:
while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)
Wenn Sie basename nicht verwenden können, wie in anderen Beiträgen vorgeschlagen, können Sie immer sed verwenden. Hier ist ein (hässliches) Beispiel. Es ist nicht das beste, aber es funktioniert, indem es die gewünschte Zeichenfolge extrahiert und die Eingabe durch die gewünschte Zeichenfolge ersetzt.
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
Damit erhalten Sie die Ausgabe
fizzbuzz