762 Stimmen

Entfernen eines festen Präfixes/Suffixes aus einem String in Bash

Ich möchte das Präfix/Suffix aus einem String entfernen. Zum Beispiel, gegeben:

string="hello-world"
prefix="hell"
suffix="ld"

Wie bekomme ich das folgende Ergebnis?

"o-wor"

1155voto

Adrian Frühwirth Punkte 38808
$ prefix="hell"
$ suffix="ld"
$ string="hello-world"
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor

Dies ist im Abschnitt zur Shell-Parameter-Expansion in der Dokumentation festgehalten:

${parameter#word}
${parameter##word}

Das Wort wird erweitert, um ein Muster zu erzeugen und entsprechend den unten beschriebenen Regeln abgeglichen (siehe Musterabgleich). Wenn das Muster mit dem Beginn des erweiterten Werts von parameter übereinstimmt, dann ist das Resultat der Erweiterung der erweiterte Wert von parameter mit dem kürzesten übereinstimmenden Muster (im Fall von #) oder dem längsten übereinstimmenden Muster (im Fall von ##

`${parameter%word}` `${parameter%%word}`

``

Das Wort wird erweitert, um ein Muster zu erzeugen und entsprechend den unten beschriebenen Regeln abgeglichen (siehe Musterabgleich). Wenn das Muster mit einem abschließenden Teil des erweiterten Werts von parameter übereinstimmt, dann ist das Resultat der Erweiterung der Wert von parameter mit dem kürzesten übereinstimmenden Muster (im Fall von %) oder dem längsten übereinstimmenden Muster (im Fall von %%) gelöscht. […]

``

157voto

Chris Kolodin Punkte 1475

Mit sed:

$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor

Innerhalb des sed-Befehls entspricht das Zeichen ^ dem Textbeginn mit $prefix und das abschließende $ dem Textende mit $suffix.

Adrian Frühwirth macht einige gute Punkte in den Kommentaren unten, aber sed kann für diesen Zweck sehr nützlich sein. Die Tatsache, dass die Inhalte von $prefix und $suffix von sed interpretiert werden können entweder gut oder schlecht sein - solange Sie aufpassen, sollten Sie in Ordnung sein. Das Schöne ist, dass Sie so etwas tun können:

$ prefix='^.*ll'
$ suffix='ld$'
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor

was möglicherweise das ist, was Sie wollen, und sowohl eleganter als auch leistungsstärker ist als die Substitution von Bash-Variablen. Wenn Sie sich daran erinnern, dass mit großer Macht große Verantwortung einhergeht (wie Spiderman sagt), sollten Sie in Ordnung sein.

Eine kurze Einführung in sed finden Sie unter http://evc-cit.info/cit052/sed_tutorial.html

Eine Anmerkung zur Shell und ihrem Umgang mit Zeichenketten:

Für das spezielle gegebene Beispiel würde auch Folgendes funktionieren:

$ echo $string | sed -e s/^$prefix// -e s/$suffix$//

...aber nur weil:

  1. echo ist es egal, wie viele Zeichenketten in seiner Argumentenliste sind, und
  2. Es gibt keine Leerzeichen in $prefix und $suffix

Es ist im Allgemeinen eine gute Praxis, eine Zeichenkette in der Befehlszeile in Anführungszeichen zu setzen, weil sie selbst dann als ein einzelnes Argument an den Befehl übergeben wird, wenn sie Leerzeichen enthält. Wir setzen $prefix und $suffix in Anführungszeichen aus dem gleichen Grund: Jeder Edit-Befehl an sed wird als eine Zeichenkette übergeben. Wir verwenden doppelte Anführungszeichen, weil sie eine Variableninterpolation ermöglichen; wenn wir einfache Anführungszeichen verwendet hätten, hätte der sed-Befehl ein wörtliches $prefix und $suffix erhalten, was sicherlich nicht das war, was wir wollten.

Bemerkenswert ist auch die Verwendung von einfachen Anführungszeichen beim Setzen der Variablen prefix und suffix. Wir möchten sicherlich nicht, dass etwas in den Zeichenketten interpretiert wird, daher setzen wir sie in einfache Anführungszeichen, damit keine Interpolation stattfindet. Auch wenn es in diesem Beispiel möglicherweise nicht notwendig ist, ist es eine sehr gute Angewohnheit, sich das anzueignen.

28voto

$ string="hello-world"
$ prefix="hell"
$ suffix="ld"

$ #remove "hell" from "hello-world" if "hell" is found at the beginning.
$ prefix_removed_string=${string/#$prefix}

$ #remove "ld" from "o-world" if "ld" is found at the end.
$ suffix_removed_String=${prefix_removed_string/%$suffix}
$ echo $suffix_removed_String
o-wor

Notizen:

$prefix : Das Hinzufügen von # stellt sicher, dass der Teilstring "hell" nur entfernt wird, wenn er am Anfang gefunden wird. %$suffix : Das Hinzufügen von % stellt sicher, dass der Teilstring "ld" nur entfernt wird, wenn er am Ende gefunden wird.

Ohne diese Zeichen würden die Teilstrings "hell" und "ld" überall entfernt werden, auch wenn sie in der Mitte gefunden werden.

23voto

tommy.carstensen Punkte 7912

Kennen Sie die Länge Ihres Präfix und Suffix? In Ihrem Fall:

result=$(echo $string | cut -c5- | rev | cut -c3- | rev)

Oder allgemeiner:

result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)

Aber die Lösung von Adrian Frühwirth ist echt cool! Davon wusste ich nichts!

22voto

Ich benutze grep, um Präfixe aus Pfaden zu entfernen (die von sed nicht gut behandelt werden):

echo "$input" | grep -oP "^$prefix\K.*"

\K entfernt aus dem Treffer alle Zeichen davor.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X