Funktioniert mit regulären Ausdrücken im selben CWD, aber nicht aus einem anderen Verzeichnis.

Funktioniert mit regulären Ausdrücken im selben CWD, aber nicht aus einem anderen Verzeichnis.

Ich habe einen Suchbefehl und möchte ihn aus einem beliebigen Verzeichnis mit einer $directoryVariablen 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}\$"

$directoryMit 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 -pathauf den vollständigen Pfad der Dateien passt. Diese Pfade beginnen mit dem Inhalt von , $directorygefolgt von den Verzeichnissen und Dateien, die von gefunden wurden find. Wenn also $directoryist /some/dir, -regexwird der reguläre Ausdruck mit übereinstimmen /some/dir/file-discovered-by-findund 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 $directoryob es gab ..

Sie müssten etwas Ähnliches mit tun $directoryund 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 extendglobkö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 $directorybeginnt mit-
  • gibt Ihnen eine sortierte Liste
  • in ist zshdie [a-zA-Z0-9]Übereinstimmung nicht zufällig und variiert nicht je nach Gebietsschema wie in findund stimmt mit den Zeichen überein, die Sie vermutlich übereinstimmen möchten, und nur mit diesen. In findmüssten Sie [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]das Äquivalent erhalten.
  • es funktioniert auch, wenn $directoryes sich um einen symbolischen Link zu einem Verzeichnis handelt (Sie können dafür jedoch die -HOption 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. zshGlobs ist eine der wenigen Musterabgleich-APIs, die den Abgleich von Zahlenbereichen unterstützen.

verwandte Informationen