486 Stimmen

Wie entferne ich die letzten n Zeichen aus einem String in Bash?

Ich habe eine Variable var in einem Bash-Skript, die einen String enthält:

echo $var
"some string.rtf"

Ich möchte die letzten vier Zeichen dieses Strings entfernen und das Ergebnis der neuen Variable var2 zuweisen, so dass

echo $var2
"some string"

Wie kann ich das machen?

455voto

onur Punkte 6085

Sie können dies so machen (in bash v4 und höher):

#!/bin/bash

v="some string.rtf"

v2=${v::-4}

echo "$v --> $v2"

Hinweis: MacOS verwendet standardmäßig bash 3.x

327voto

Etan Reisner Punkte 73442

Um vier Zeichen vom Ende des Strings zu entfernen, verwenden Sie ${var%????}.

Um alles nach und einschließlich des letzten . zu entfernen, verwenden Sie ${var%.*}.

Weitere Informationen finden Sie in der Dokumentation von Bash zur Parametererweiterung.

166voto

Mark Reed Punkte 85468

Zuerst ist es in der Regel besser, seinen Zweck genau zu benennen. Wenn Sie also wissen, dass der String mit einem .rtf endet, den Sie entfernen möchten, können Sie einfach var2=${var%.rtf} verwenden. Ein potenziell nützlicher Aspekt dieses Ansatzes ist, dass wenn der String nicht mit .rtf endet, überhaupt nichts geändert wird; var2 wird eine unveränderte Kopie von var enthalten.

Wenn Sie einen Dateinamensuffix entfernen möchten, aber nicht genau wissen oder interessieren, was es ist, können Sie var2=${var%.*} verwenden, um alles ab dem letzten . zu entfernen. Oder wenn Sie nur alles bis zum ersten . behalten möchten, können Sie var2=${var%%.*} verwenden. Diese Optionen haben das gleiche Ergebnis, wenn es nur ein . im String gibt, aber wenn es mehr als eine geben könnte, können Sie wählen, von welchem Ende des Strings aus gearbeitet werden soll. Wenn andererseits überhaupt kein . im String vorhanden ist, wird var2 wieder eine unveränderte Kopie von var sein.

Wenn Sie wirklich immer eine bestimmte Anzahl von Zeichen entfernen möchten, gibt es hier einige Optionen.

Sie haben dies speziell mit bash markiert, also werden wir mit den Bash-Builtin-Funktionen beginnen. Diejenige, die am längsten funktioniert hat, ist die gleiche Suffix-Entfernungssyntax, die ich oben verwendet habe: Um vier Zeichen zu entfernen, verwenden Sie var2=${var%????}. Oder um nur vier Zeichen zu entfernen, wenn das erste ein Punkt ist, verwenden Sie var2=${var%.???}, was ähnlich wie var2=${var%.*} ist, aber nur den Suffix entfernt, wenn der Teil nach dem Punkt genau drei Zeichen lang ist. Wie Sie sehen, benötigen Sie pro unbekanntes Zeichen, das entfernt wird, ein Fragezeichen, daher wird dieser Ansatz bei größeren Teilzeichenlängen umständlich.

Eine Option in neueren Shell-Versionen ist die Teilzeichenfolgenextraktion: var2=${var:0:${#var}-4}. Hier können Sie eine beliebige Zahl anstelle der 4 eingeben, um eine andere Anzahl von Zeichen zu entfernen. Das ${#var} wird durch die Länge des Strings ersetzt, sodass hier tatsächlich gefragt wird, (Länge - 4) Zeichen zu extrahieren und zu behalten, beginnend mit dem ersten (bei Index 0). Mit diesem Ansatz verlieren Sie die Möglichkeit, die Änderung nur dann vorzunehmen, wenn der String zu einem Muster passt. Solange der String mindestens vier Zeichen lang ist, unabhängig von seinem tatsächlichen Wert, enthält die Kopie alles außer den letzten vier Zeichen.

Sie können den Startindex weglassen; es ist standardmäßig auf 0 gesetzt, sodass Sie das einfach auf var2=${var::${#var}-4} verkürzen können. Tatsächlich erkennen neuere Versionen von Bash (speziell 4+, was bedeutet, dass die mit MacOS mitgelieferte nicht funktioniert) negative Längen als den Index des Zeichens, an dem aufgehört werden soll, und zählen von hinten vom Ende des Strings. In diesen Versionen können Sie also auch den Ausdruck zur Bestimmung der Stringlänge weglassen: var2=${var::-4}. Diese Interpretation wird auch angewendet, wenn Sie die Stringlänge festlegen, der String jedoch kürzer als vier Zeichen ist, da dann ${#var}-4 negativ wird. Wenn der String beispielsweise drei Zeichen hat, wird ${var:0:${#var}-4} zu ${var:0:-1} und entfernt nur das letzte Zeichen.

Wenn Sie tatsächlich nicht Bash, sondern eine andere POSIX-Shell verwenden, wird die muster basierte Suffix-Entfernung mit % immer noch funktionieren – selbst in der einfachen alten Dash-Shell, in der die indexbasierte Teilzeichenfolgenextraktion nicht funktioniert. Ksh und Zsh unterstützen beide die Teilzeichenfolgenextraktion, erfordern jedoch den expliziten Startindex 0; Zsh unterstützt auch den negativen Endindex, während Ksh den Längenausdruck benötigt. Beachten Sie, dass Zsh standardmäßig Arrays ab 1 indiziert, aber dennoch Strings ab 0 indiziert, wenn Sie diese bash-kompatible Syntax verwenden. Aber Zsh ermöglicht es Ihnen auch, skalare Parameter so zu behandeln, als wären sie Arrays von Zeichen, wodurch Sie eine Teilzeichenfolge mit der Array-Slice-Syntax [start, end] erstellen können, wobei das Ende inklusiv ist und als negative Zahl angegeben werden kann, die rückwärts vom Ende zählt: var2=$var[1,-5].

Statt der Verwendung der integrierten Shell-Parametererweiterung können Sie natürlich ein Dienstprogramm ausführen, um den String zu ändern, und dessen Ausgabe mit Befehlsersetzung erfassen. Es gibt mehrere Befehle, die funktionieren werden; einer davon ist var2=$(sed 's/.\{4\}$//' <<<"$var").

134voto

Reut Sharabani Punkte 28873

Was für mich funktioniert hat, war:

echo "Hallo Welt" | rev | cut -c5- | rev
# Hallo W

Aber ich habe es benutzt, um Zeilen in einer Datei zu kürzen, deshalb sieht es seltsam aus. Der eigentliche Gebrauch war:

cat irgendwelcheDatei | rev | cut -c5- | rev

cut bringt Sie nur bis zu einem gewissen Startpunkt, was schlecht ist, wenn Sie Zeilen variabler Länge benötigen. Deshalb kehrt diese Lösung (rev) den String um und bezieht sich jetzt auf seine Endposition, verwendet dann cut wie erwähnt und kehrt ihn (wieder, rev) zurück in seine ursprüngliche Reihenfolge.

50voto

fredtantini Punkte 16076

Mit Variablenerweiterung/Substring-Ersetzung:

${var/%Pattern/Replacement}

Wenn das Suffix von var mit Pattern übereinstimmt, dann ersetze Pattern durch Replacement.

Also kannst du:

~$ echo ${var/%????/}
some string

Alternativ,

Wenn du immer die gleichen 4 Buchstaben hast

~$ echo ${var/.rtf/}
some string

Wenn es immer auf .xyz endet:

~$ echo ${var%.*}
some string

Du kannst auch die Länge des Strings verwenden:

~$ len=${#var}
~$ echo ${var::len-4}
some string

oder einfach echo ${var::-4}

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