1114 Stimmen

Teilstring in Bash extrahieren

Angesichts eines Dateinamens in der Form someletters_12345_moreleters.ext Ich möchte die 5 Ziffern extrahieren und sie in eine Variable einfügen.

Um das zu verdeutlichen, habe ich einen Dateinamen mit einer Anzahl von x Zeichen, dann eine fünfstellige Sequenz, die von einem einzelnen Unterstrich auf beiden Seiten umgeben ist, und dann eine weitere Reihe von x Zeichen. Ich möchte die fünfstellige Zahl nehmen und sie in eine Variable einfügen.

Ich bin sehr daran interessiert, wie viele verschiedene Möglichkeiten es gibt, dies zu erreichen.

1602voto

JB. Punkte 37289

Sie können verwenden Parameter Erweiterung um dies zu tun.

Si a konstant ist, führt die folgende Parametererweiterung eine Teilstring-Extraktion durch:

b=${a:12:5}

donde 12 ist der Offset (nullbasiert) und 5 ist die Länge

Wenn die Unterstriche um die Ziffern die einzigen in der Eingabe sind, können Sie das Präfix und das Suffix (jeweils) in zwei Schritten entfernen:

tmp=${a#*_}   # remove prefix ending in "_"
b=${tmp%_*}   # remove suffix starting with "_"

Wenn es andere Unterstriche gibt, ist es wahrscheinlich trotzdem machbar, wenn auch schwieriger. Wenn jemand weiß, wie man beide Expansionen in einem einzigen Ausdruck durchführen kann, würde ich das auch gerne wissen.

Beide vorgestellten Lösungen sind reine Bash-Lösungen, ohne Prozess-Spawning, und daher sehr schnell.

930voto

FerranB Punkte 33783

Verwenden Sie schneiden :

echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2

Mehr generisch:

INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING

136voto

brown.2179 Punkte 1530

Versuchen Sie einfach, die cut -c startIndx-stopIndx

129voto

Allgemeine Lösung, bei der die Nummer an beliebiger Stelle im Dateinamen stehen kann, unter Verwendung der ersten dieser Sequenzen:

number=$(echo $filename | egrep -o '[[:digit:]]{5}' | head -n1)

Eine andere Lösung, um genau einen Teil einer Variablen zu extrahieren:

number=${filename:offset:length}

Wenn Ihr Dateiname immer das Format stuff_digits_... können Sie awk verwenden:

number=$(echo $filename | awk -F _ '{ print $2 }')

Eine weitere Lösung, um alles außer Ziffern zu entfernen, ist die Verwendung von

number=$(echo $filename | tr -cd '[[:digit:]]')

60voto

nicerobot Punkte 8777

Ich würde es folgendermaßen machen:

FN=someletters_12345_moreleters.ext
[[ ${FN} =~ _([[:digit:]]{5})_ ]] && NUM=${BASH_REMATCH[1]}

Erläuterung:

Basisspezifisch:

Reguläre Ausdrücke (RE): _([[:digit:]]{5})_

  • _ sind Literale zur Abgrenzung/Verankerung der übereinstimmenden Grenzen für die übereinstimmende Zeichenfolge
  • () eine Erfassungsgruppe erstellen
  • [[:digit:]] ist eine Charakterklasse, ich denke, das spricht für sich
  • {5} bedeutet, dass genau fünf der vorherigen Zeichen, Klassen (wie in diesem Beispiel) oder Gruppen übereinstimmen müssen

Auf Englisch kann man sich das wie folgt vorstellen: Die FN Zeichenkette wird Zeichen für Zeichen durchlaufen, bis wir eine _ dann wird die Fanggruppe geöffnet und wir versuchen, fünf Ziffern zu finden. Wenn dieser Abgleich bis zu diesem Punkt erfolgreich ist, speichert die Erfassungsgruppe die fünf durchlaufenen Ziffern. Wenn das nächste Zeichen ein _ Wenn die Bedingung erfüllt ist, wird die Erfassungsgruppe in BASH_REMATCH und die nächste NUM= Anweisung ausgeführt werden kann. Wenn ein Teil des Abgleichs fehlschlägt, werden die gespeicherten Details verworfen und die zeichenweise Verarbeitung wird nach der _ . z.B. wenn FN donde _1 _12 _123 _1234 _12345_ Es gab vier Fehlstarts, bevor es eine Übereinstimmung fand.

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