Wenn Sie Bash verwenden, müssen Sie nicht einmal Folgendes verwenden grep
:
files="*.jpg"
regex="[0-9]+_([a-z]+)_[0-9a-z]*"
for f in $files # unquoted in order to allow the glob to expand
do
if [[ $f =~ $regex ]]
then
name="${BASH_REMATCH[1]}"
echo "${name}.jpg" # concatenate strings
name="${name}.jpg" # same thing stored in a variable
else
echo "$f doesn't match" >&2 # this could get noisy if there are a lot of non-matching files
fi
done
Es ist besser, den regulären Ausdruck in eine Variable zu setzen. Einige Muster funktionieren nicht, wenn sie wörtlich enthalten sind.
Dies verwendet =~
den Regex-Match-Operator von Bash. Die Ergebnisse der Übereinstimmung werden in einem aufgerufenen Array gespeichert $BASH_REMATCH
. Die erste Erfassungsgruppe wird in Index 1 gespeichert, die zweite (falls vorhanden) in Index 2 usw. Index Null ist die vollständige Übereinstimmung.
Sie sollten sich bewusst sein, dass dieser Regex (und der verwendete grep
) ohne Anker mit einem der folgenden Beispiele und mehr übereinstimmt, die möglicherweise nicht das sind, wonach Sie suchen:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Um das zweite und vierte Beispiel zu eliminieren, machen Sie Ihren regulären Ausdruck wie folgt:
^[0-9]+_([a-z]+)_[0-9a-z]*
was sagt der Zeichenfolge muss beginnen mit einem oder mehreren Ziffern. Das Karat repräsentiert den Anfang der Saite. Wenn Sie am Ende der Regex ein Dollarzeichen hinzufügen, gehen Sie wie folgt vor:
^[0-9]+_([a-z]+)_[0-9a-z]*$
dann wird auch das dritte Beispiel entfernt, da der Punkt nicht zu den Zeichen in der Regex gehört und das Dollarzeichen das Ende der Zeichenfolge darstellt. Beachten Sie, dass das vierte Beispiel auch diese Übereinstimmung nicht besteht.
Wenn Sie GNU haben grep
(ungefähr 2,5 oder höher, denke ich, als der \K
Operator hinzugefügt wurde):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
Der \K
Operator (Look-Behind mit variabler Länge) bewirkt, dass das vorhergehende Muster übereinstimmt, schließt die Übereinstimmung jedoch nicht in das Ergebnis ein. Das Äquivalent fester Länge ist (?<=)
- das Muster würde vor der schließenden Klammer stehen. Sie müssen verwenden , \K
wenn quantifiers können Strings unterschiedlicher Länge (zB übereinstimmen +
, *
, {2,4}
).
Der (?=)
Operator stimmt mit Mustern fester oder variabler Länge überein und wird als "Vorausschau" bezeichnet. Die übereinstimmende Zeichenfolge ist auch nicht im Ergebnis enthalten.
Um die Übereinstimmung zwischen Groß- und Kleinschreibung zu unterscheiden, wird der (?i)
Operator verwendet. Es beeinflusst die Muster, die ihm folgen, so dass seine Position signifikant ist.
Die Regex muss möglicherweise angepasst werden, je nachdem, ob der Dateiname andere Zeichen enthält. Sie werden feststellen, dass in diesem Fall ein Beispiel für die Verkettung einer Zeichenfolge zur gleichen Zeit gezeigt wird, zu der der Teilstring erfasst wird.