Ich habe einen Suchbefehl und möchte ihn aus einem beliebigen Verzeichnis mit einer $directory
Variablen anstelle des Punkts .
für das aktuelle Arbeitsverzeichnis ausführen.
Was funktioniert ist dies
- Beispiel 1
find $directory -maxdepth 1 -type d -name "test*"
Das gibt mir einige Ergebnisse.
Auch das funktioniert
- Beispiel 2
find . -maxdepth 1 -type d -regextype posix-extended -regex "^./[a-zA-Z0-9]+([-_]?[a-zA-Z0-9]+)*-[0-9]{1,3}(.[0-9]{1,3}){,3}\$"
$directory
Mit einem funktioniert es jedoch nicht. Beachten Sie, dass ich das ./
am Anfang des regulären Ausdrucks entfernt habe.
- Beispiel 3
find $directory -maxdepth 1 -type d -regextype posix-extended -regex "^[a-zA-Z0-9]+([-_]?[a-zA-Z0-9]+)*-[0-9]{1,3}(.[0-9]{1,3}){,3}\$"
Warum ist das so?
Danke
Antwort1
-regex
(nicht Standard), da der Standard -path
auf den vollständigen Pfad der Dateien passt. Diese Pfade beginnen mit dem Inhalt von , $directory
gefolgt von den Verzeichnissen und Dateien, die von gefunden wurden find
. Wenn also $directory
ist /some/dir
, -regex
wird der reguläre Ausdruck mit übereinstimmen /some/dir/file-discovered-by-find
und hier nie übereinstimmen, da das erste Zeichen ein ist /
, keine Zahl.
Im ersten Fall begann Ihr regulärer Ausdruck mit ^./
(hätte lauten sollen, ^\./
da .
es sich um einen regulären Ausdrucksoperator handelt, oder einfach \./
wie ^
in GNUs impliziert ist find
) -regex
, als $directory
ob es gab .
.
Sie müssten etwas Ähnliches mit tun $directory
und dabei bedenken, dass alle Regexp-Operatoren in $directory
( ^$*()+[]?.\
...) maskiert werden müssten. Aber hier können Sie genauso gut Folgendes tun:
find "$directory" -maxdepth 1 -type d -regextype posix-extended \
-regex '.*/[[:alnum:]]+([-_][[:alnum:]]+)*-[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){0,3}'
(Ich habe außerdem .
durch ersetzt, da ich vermute, dass Sie einen Literalwert und nicht nur ein beliebiges Zeichen \.
abgleichen möchten , und entfernt , was hier nicht notwendig war.).
?
Das bedeutet, dass Ihr Muster (das hier garantiert kein enthält /
) nach jedem /
(und bis zum Ende des Dateipfads, wie $
ebenfalls impliziert) übereinstimmen muss und nicht nach etwas, das mit übereinstimmt $directory
.
Mit zsh -o extendglob
können Sie Folgendes tun:
set -o extendedglob
w=[0-9a-zA-Z] d=[0-9]
print -rC1 -- $directory/$~w##([-_]$~w##)#-$~d(#c1,3)(.$~d(#c1,3))(#c0,3)(#q/)
Dies hat gegenüber GNU mehrere Vorteile find
:
- würde sogar auf Nicht-GNU-Systemen funktionieren (entfernt die Abhängigkeit zu GNU
find
) - funktioniert auch wenn
$directory
beginnt mit-
- gibt Ihnen eine sortierte Liste
- in ist
zsh
die[a-zA-Z0-9]
Übereinstimmung nicht zufällig und variiert nicht je nach Gebietsschema wie infind
und stimmt mit den Zeichen überein, die Sie vermutlich übereinstimmen möchten, und nur mit diesen. Infind
müssten Sie[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]
das Äquivalent erhalten. - es funktioniert auch, wenn
$directory
es sich um einen symbolischen Link zu einem Verzeichnis handelt (Sie können dafür jedoch die-H
Option hinzufügen).find
- es funktioniert sogar, wenn die Dateipfade (in diesem Fall der Inhalt von
$directory
) Bytefolgen enthalten, die im aktuellen Gebietsschema keine gültigen Zeichen bilden (find
's-regex
's.*
konnten hier nicht übereinstimmen, da.
nur gültige Zeichen übereinstimmen). - Anstatt die Liste auszudrucken, können Sie sie direkt verwenden (als Argumente für einen Befehl, um eine Schleife darüber auszuführen usw.).
- Sie können beispielsweise auch Dinge verwenden, um
(<0-255>~????*)
Dezimalzahlen von 0 bis 255 mit maximal 3 Ziffern oder(<0-255>~0?*)
Zahlen ohne führende 0 abzugleichen.zsh
Globs ist eine der wenigen Musterabgleich-APIs, die den Abgleich von Zahlenbereichen unterstützen.