Ich verwende den ls
Befehl in Bash und versuche, alle Dateien oder Verzeichnisse der Länge n zu finden. Nehmen wir an, n = 5
Mein Befehl ist:
ls ?????
Dies würde jedoch auch Zeichen einschließen, die keine Buchstaben sind, wie z. B. Punkte. Die folgenden Dateien würden beispielsweise übereinstimmen:
ab.cd
abd.c
Ich möchte nur Dateien abgleichen, deren Namen aus 5 Buchstaben oder Zahlen bestehen:
five1
five2
five3
Aber nicht
abc.d
ab.cd
a.bcd
Wie kann ich meinen Befehl ändern?
Antwort gefunden:
ls [a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]
Ich habe die Antwort gefunden, aber wie kann ich es weniger hässlich machen?
Antwort1
Beachten Sie, dass ls
diese Globs nicht von interpretiert werden. Diese Globs werden von Ihrer Shell in eine Liste von Dateinamen erweitert, die als Argumente an übergeben wird ls
. Verschiedene Shells haben unterschiedliche Globbing-Fähigkeiten. bash
hat einige Erweiterungen gegenüber Standard-Globs (entlehnt von ksh88
und aktiviert mit shopt -s extglob
), ist aber immer noch im Vergleich zu Shells wie zsh
oder eingeschränkt ksh93
.
Mit zsh
:
setopt extendedglob
ls -d [[:alnum:]](#c5)
ksh93
:
ls -d {5}([[:alnum:]])
oder:
ls -d {5}(\w) # (\w includes underscore in addition to alnums)
oder, wenn Sie erweiterte reguläre Ausdrücke verwenden möchten:
ls -d ~(E)^[[:alnum:]]{5}$
Mit bash
oder anderen POSIX-Shells, die keine entsprechenden Globbing-Operatoren haben, müssen Sie Folgendes tun:
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
Beachten Sie, dass [[:alnum:]]
alle alphabetischen Zeichen der aktuellen Ländereinstellung (nicht nur lateinische Alphabete, geschweige denn das englische) und 0123456789
(und möglicherweise andere Arten von Ziffern) eingeschlossen sind. Wenn Sie die Buchstaben des englischen Alphabets möchten, benennen Sie die Zeichen einzeln:
c='[0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]'
unset -v IFS
ls -d $c$c$c$c$c
Oder verwenden Sie das Gebietsschema C:
(export LC_ALL=C
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]])
Antwort2
ls -q | grep -Ex '[[:alnum:]]{5}'
Antwort3
ls
Wenn Sie die Funktion auf die von Ihnen genannte Weise verwenden möchten , sollten Sie die -d
Option verwenden. Andernfalls wird dieInhaltvon irgendwelchenVerzeichnisse
deren Namen aus fünf Buchstaben und/oder Ziffern bestehen, anstatt die Namen selbst aufzulisten. Sie können auch
ls -d [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
aber das ist genauso viel Tipparbeit wie die Antwort, die Sie jetzt haben.
Auch wenn Sie nichtbrauchenls
Um in Ihrem Befehl zu verwenden , könnten Sie verwenden
echo [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]
Dadurch werden alle Übereinstimmungen in einer Zeile aufgelistet, oder
printf "%s\n" [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][:alnum:]]
Dadurch werden sie in separaten Zeilen aufgelistet.
Antwort4
Bauen Sie den Ausdruck in einer Variablen auf:
e=""; for m in $(seq 1 5); do e="$e[A-Za-z0-9]"; done
Fügen Sie es in eine Funktion ein, damit es schick/wiederverwendbar ist:
alnumglob() {
local e=""
for m in $(seq 1 $1) ; do e="$e[A-Za-z0-9]"; done
echo "$e"
}
ls -ld $(alnumglob 5)