Найти работу с регулярным выражением в том же CWD, но не из другого каталога

Найти работу с регулярным выражением в том же CWD, но не из другого каталога

У меня есть команда find, и я хотел бы выполнить ее из произвольного каталога с $directoryпеременной вместо точки .для текущего рабочего каталога.

Что работает, так это

  • Пример 1
find $directory -maxdepth 1 -type d -name "test*"

Это дает мне некоторые результаты.

Это тоже работает

  • Пример 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}\$"

Однако с a $directoryэто не работает. Обратите внимание, что я удалил the ./в начале регулярного выражения.

  • Пример 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}\$"

Почему это так?

Спасибо

решение1

-regex(не стандартный), как и стандартные -pathсовпадения по полному пути файлов. Эти пути начинаются с содержимого , за которым $directoryследуют каталоги и файлы, найденные find. Так что если $directoryесть /some/dir, -regexбудет соответствовать регулярному выражению по /some/dir/file-discovered-by-find, и никогда не будет соответствовать здесь, так как первый символ — это /, а не alnum.

В первом случае ваше регулярное выражение начиналось с ^./(так и должно было быть, ^\./поскольку .это оператор регулярного выражения или как \./подразумевается ^в GNU find), -regexпоскольку $directoryтам было ..

Вам нужно сделать что-то похожее с $directory, имея в виду, что все операторы регулярных выражений в $directory( ^$*()+[]?.\...) должны быть экранированы. Но здесь вы можете сделать так же:

find "$directory" -maxdepth 1 -type d -regextype posix-extended \
  -regex '.*/[[:alnum:]]+([-_][[:alnum:]]+)*-[[:digit:]]{1,3}(\.[[:digit:]]{1,3}){0,3}'

(Я также заменил .на , \.поскольку подозреваю, что вы хотите сопоставить букву ., а не просто любой символ, и удалил , ?который здесь не нужен).

То есть, ваш шаблон (который здесь гарантированно не будет включать в себя /) должен соответствовать любому /(и до конца пути к файлу, что $также подразумевается), а не чему-то, что соответствует $directory.

С помощью zsh -o extendglobвы можете сделать:

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/)

Который имеет несколько преимуществ по сравнению с GNU find:

  • будет работать даже на не-GNU системах (устраняет зависимость от GNU find)
  • работает даже если $directoryначинается с-
  • дает вам отсортированный список
  • в zsh, то, что [a-zA-Z0-9]соответствует, не является случайным и не меняется в зависимости от локалей, как в findи соответствует символам, которые, как я полагаю, вы хотите сопоставить, и только им. В find, вам нужно будет [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]получить эквивалент.
  • это работает, даже если $directoryэто символическая ссылка на каталог (хотя вы можете добавить -Hопцию findдля этого).
  • это работает, даже если пути к файлам (в данном случае содержимое $directory) содержат последовательность байтов, которые не образуют допустимые символы в текущей локали ( find' -regex' .*не могут совпадать с ними, поскольку .соответствуют только допустимым символам).
  • Вместо того, чтобы печатать этот список, вы можете использовать его напрямую (в качестве аргументов команды, для выполнения цикла и т. д.)
  • Вы также можете использовать такие вещи, как (<0-255>~????*)сопоставление десятичных чисел от 0 до 255, состоящих не более чем из 3 цифр, или (<0-255>~0?*)для чисел без начального нуля, поскольку zshglobs является одним из немногих API сопоставления с шаблоном, которые поддерживают сопоставление диапазонов чисел.

Связанный контент