Bei einem Dateinamen im Formular someletters_12345_moreleters.ext
möchte ich die 5 Ziffern extrahieren und in eine Variable einfügen.
Um den Punkt hervorzuheben, habe ich einen Dateinamen mit x Zeichenanzahl, dann eine fünfstellige Folge, die auf beiden Seiten von einem einzelnen Unterstrich umgeben ist, und dann einen weiteren Satz von x Zeichenanzahl. Ich möchte die 5-stellige Zahl nehmen und in eine Variable einfügen.
Ich bin sehr interessiert an der Anzahl der verschiedenen Möglichkeiten, wie dies erreicht werden kann.
abc_12345_def_67890_ghi_def
ist eine gültige Eingabe. Was willst du passieren? Nehmen wir an, es gibt nur eine 5-stellige Sequenz. Sie haben nochabc_def_12345_ghi_jkl
oder1234567_12345_1234567
oder12345d_12345_12345e
als gültige Eingabe basierend auf Ihrer Definition der Eingabe und die meisten der folgenden Antworten werden dies nicht behandeln._
Trennzeichen, Eingabe, die die Zielzeichenfolge nur einmal enthält usw.). Die beste (allgemeinste und schnellste) Antwort hat nach 10 Jahren nur 7 positive Stimmen, während andere begrenzte Antworten Hunderte haben. Lässt mich das Vertrauen in Entwickler verlierenAntworten:
Verwenden Sie Schnitt :
Allgemeiner:
quelle
echo
sei denn, Sie wissen sicher, dass die Variablen keine unregelmäßigen Leerzeichen oder Shell-Metazeichen enthalten können. Siehe weitere stackoverflow.com/questions/10067266/…Wenn x konstant ist, führt die folgende Parametererweiterung eine Teilzeichenfolgenextraktion durch:
Dabei ist 12 der Versatz (nullbasiert) und 5 die Länge
Wenn die Unterstriche um die Ziffern die einzigen in der Eingabe sind, können Sie das Präfix bzw. das Suffix in zwei Schritten entfernen:
Wenn es andere Unterstriche gibt, ist es wahrscheinlich sowieso machbar, wenn auch schwieriger. Wenn jemand weiß, wie man beide Erweiterungen in einem einzigen Ausdruck ausführt, würde ich es auch gerne wissen.
Beide vorgestellten Lösungen sind reine Bashs, ohne dass Prozesslaichen erforderlich sind, daher sehr schnell.
quelle
bash: ${${a#*_}%_*}: bad substitution
auf meiner GNU-Bash 4.2.45.sh
Skript aus, das wahrscheinlich ein Strich war. Zu diesem Zeitpunkt kann ich es nicht mehr zum Laufen bringen.:-
Ersatz für "Standardwerte verwenden" interpretiert . So${a: -12:5}
ergeben sich die 5 Zeichen 12 Zeichen vom Ende und${a: -12:-5}
die 7 Zeichen zwischen Ende-12 und Ende-5.Generische Lösung, bei der die Nummer an einer beliebigen Stelle im Dateinamen stehen kann, wobei die erste dieser Sequenzen verwendet wird:
Eine andere Lösung, um genau einen Teil einer Variablen zu extrahieren:
Wenn Ihr Dateiname immer das Format
stuff_digits_...
hat, können Sie awk verwenden:Verwenden Sie noch eine andere Lösung, um alles außer Ziffern zu entfernen
quelle
versuche es einfach zu benutzen
cut -c startIndx-stopIndx
quelle
startIndx-$((lastIndx-1))
start=5;stop=9; echo "the rain in spain" | cut -c $start-$(($stop-1))
git log --oneline | head -1 | cut -c 9-(end -1)
line=
git log --oneline | gebrochen wird head -1` && echo $ line | cut -c 9 - $ (($ {# line} -1)) `aber in diesem speziellen Fall ist es möglicherweise besser, sed alsgit log --oneline | head -1 | sed -e 's/^[a-z0-9]* //g'
Falls jemand strengere Informationen wünscht, können Sie diese auch in Man Bash wie diesen suchen
Ergebnis:
quelle
${var: -4}
So würde ich es machen:
Erläuterung:
Bash-spezifisch:
[[ ]]
zeigt einen bedingten Ausdruck an=~
gibt an, dass die Bedingung ein regulärer Ausdruck ist&&
verkettet die Befehle, wenn der vorherige Befehl erfolgreich warReguläre Ausdrücke (RE):
_([[:digit:]]{5})_
_
sind Literale, um Übereinstimmungsgrenzen für die übereinstimmende Zeichenfolge abzugrenzen / zu verankern()
Erstellen Sie eine Erfassungsgruppe[[:digit:]]
ist eine Charakterklasse, ich denke sie spricht für sich{5}
bedeutet, dass genau fünf der vorherigen Zeichen, Klassen (wie in diesem Beispiel) oder Gruppen übereinstimmen müssenAuf Englisch können Sie sich vorstellen, dass es sich so verhält: Die
FN
Zeichenfolge wird zeichenweise wiederholt, bis wir sehen,_
an welchem Punkt die Erfassungsgruppe geöffnet wird, und wir versuchen, fünf Ziffern zuzuordnen. Wenn dieser Abgleich bis zu diesem Punkt erfolgreich ist, speichert die Erfassungsgruppe die fünf durchquerten Ziffern. Wenn das nächste Zeichen ein ist_
, ist die Bedingung erfolgreich, die Erfassungsgruppe wird in verfügbar gemachtBASH_REMATCH
und die nächsteNUM=
Anweisung kann ausgeführt werden. Wenn ein Teil des Abgleichs fehlschlägt, werden gespeicherte Details entsorgt und die zeichenweise Verarbeitung wird nach dem fortgesetzt_
. zB wennFN
wo_1 _12 _123 _1234 _12345_
, würde es vier Fehlstarts geben, bevor es eine Übereinstimmung gefunden hat.quelle
cut
). Es ist auch nicht auf die Ausführung eines externen Befehls angewiesen.Ich bin überrascht, dass diese reine Bash-Lösung nicht aufgetaucht ist:
Sie möchten IFS wahrscheinlich auf den Wert zurücksetzen, der vorher oder
unset IFS
nachher war!quelle
IFS
Parameter nicht gesetzt und positioniert werden müssen:IFS=_ read -r _ digs _ <<< "$a"; echo "$digs"
Aufbauend auf Jors Antwort (was bei mir nicht funktioniert):
quelle
cut
es.Den Anforderungen folgen
Ich habe einige
grep
Möglichkeiten gefunden, die nützlich sein können:oder besser
Und dann mit
-Po
Syntax:Oder wenn Sie möchten, dass es genau 5 Zeichen passt:
Um es in einer Variablen zu speichern, muss nur die
var=$(command)
Syntax verwendet werden.quelle
Invocation as 'egrep' is deprecated; use 'grep -E' instead
. Ich habe deine Antwort bearbeitet.Wenn wir uns auf das Konzept konzentrieren:
"Eine Folge von (einer oder mehreren) Ziffern"
Wir könnten mehrere externe Tools verwenden, um die Zahlen zu extrahieren.
Wir könnten ganz leicht alle anderen Zeichen löschen, entweder sed oder tr:
Wenn $ name jedoch mehrere Zahlenläufe enthält, schlägt Folgendes fehl:
Wenn "name = someletters_12345_moreleters_323_end.ext", dann:
Wir müssen regelmäßige Ausdrücke (Regex) verwenden.
So wählen Sie nur den ersten Lauf (12345, nicht 323) in sed und perl aus:
Aber wir könnten es genauso gut direkt in bash (1) tun :
Auf diese Weise können wir den ERSTEN Ziffernlauf beliebiger Länge extrahieren, der
von anderen Texten / Zeichen umgeben ist.
Hinweis :
regex=[^0-9]*([0-9]{5,5}).*$;
Entspricht nur genau 5-stelligen Läufen. :-)(1) : schneller als das Aufrufen eines externen Tools für jeden Kurztext. Nicht schneller als die gesamte Verarbeitung in sed oder awk für große Dateien.
quelle
Ohne Unterprozesse können Sie:
Eine sehr kleine Variante davon funktioniert auch in ksh93.
quelle
Hier ist eine Präfix-Suffix-Lösung (ähnlich den von JB und Darron angegebenen Lösungen), die mit dem ersten Ziffernblock übereinstimmt und nicht von den umgebenden Unterstrichen abhängt:
quelle
Ich liebe
sed
die Fähigkeit, mit Regex-Gruppen umzugehen:Eine etwas allgemeinere Option wäre, nicht anzunehmen, dass Sie einen Unterstrich haben
_
, der den Beginn Ihrer Ziffernfolge markiert, und beispielsweise alle Nicht-Zahlen, die Sie vor Ihrer Sequenz erhalten, entfernen :s/[^0-9]\+\([0-9]\+\).*/\1/p
.Mehr dazu, falls Sie mit regulären Ausdrücken nicht allzu sicher sind:
s
ist für _s_ubstitute[0-9]+
entspricht 1+ Ziffern\1
Links zur Gruppe Nr. 1 der Regex-Ausgabe (Gruppe 0 ist die gesamte Übereinstimmung, Gruppe 1 ist in diesem Fall die Übereinstimmung in Klammern)p
Flag ist für _p_rintingAlle Escapezeichen
\
sind dazu da, dasssed
die Regexp-Verarbeitung funktioniert.quelle
Meine Antwort hat mehr Kontrolle darüber, was Sie von Ihrem String erwarten. Hier ist der Code, wie Sie
12345
aus Ihrer Zeichenfolge extrahieren könnenDies ist effizienter, wenn Sie etwas extrahieren möchten, das Zeichen wie
abc
oder Sonderzeichen wie_
oder enthält-
. Zum Beispiel: Wenn Ihre Zeichenfolge so ist und Sie alles wollen, was nachsomeletters_
und vor ist_moreleters.ext
:Mit meinem Code können Sie genau angeben, was Sie wollen. Erläuterung:
#*
Die vorhergehende Zeichenfolge einschließlich des passenden Schlüssels wird entfernt. Hier ist der Schlüssel, den wir erwähnt haben:_
%
Er entfernt die folgende Zeichenfolge einschließlich des passenden Schlüssels. Hier ist der Schlüssel, den wir erwähnt haben, '_more *'Machen Sie selbst einige Experimente und Sie würden dies interessant finden.
quelle
Gegeben ist test.txt eine Datei, die "ABCDEFGHIJKLMNOPQRSTUVWXYZ" enthält.
quelle
Ok, hier geht reine Parameterersetzung mit einer leeren Zeichenfolge. Vorbehalt ist, dass ich Someletters und Moreletters als einzige Charaktere definiert habe . Wenn sie alphanumerisch sind, funktioniert dies nicht so wie es ist.
quelle
ähnlich wie substr ('abcdefg', 2-1, 3) in php:
quelle
Es gibt auch den eingebauten Befehl 'expr' von bash:
quelle
expr
ist kein eingebauter.=~
unterstützten Betreibers nicht erforderlich[[
.Ein bisschen spät, aber ich bin gerade auf dieses Problem gestoßen und habe Folgendes festgestellt:
Ich habe es verwendet, um eine Millisekundenauflösung auf einem eingebetteten System zu erhalten, das für das Datum nicht% N enthält:
quelle
Eine Bash-Lösung:
Dadurch wird eine aufgerufene Variable blockiert
x
. Die Varx
könnte in die Var geändert werden_
.quelle
Inklusive Ende, ähnlich wie bei JS- und Java-Implementierungen. Entfernen Sie +1, wenn Sie dies nicht wünschen.
Beispiel:
Weitere Beispielaufrufe:
Bitte schön.
quelle