Encontre como trabalhar com regexp no mesmo CWD, mas não em outro diretório

Encontre como trabalhar com regexp no mesmo CWD, mas não em outro diretório

Eu tenho um comando find e gostaria de emiti-lo a partir de um diretório arbitrário com uma $directoryvariável no lugar do ponto .do diretório de trabalho atual.

O que funciona é isso

  • Exemplo 1
find $directory -maxdepth 1 -type d -name "test*"

Isso me dá alguns resultados.

Também isso funciona

  • Exemplo 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}\$"

No entanto, com a $directoryisso não funciona. Lembre-se de que removi o ./no início do regex.

  • Exemplo 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}\$"

Por que?

Obrigado

Responder1

-regex(não padrão), como o padrão -pathcorresponde ao caminho completo dos arquivos. Esses caminhos começam com o conteúdo de $directoryseguido pelos diretórios e arquivos encontrados por find. Portanto, se $directoryfor /some/dir, -regexcorresponderá ao regex /some/dir/file-discovered-by-finde nunca corresponderá aqui, pois o primeiro caractere é a /, não um alnum.

No primeiro caso, seu regexp começou com ^./(deveria ter sido ^\./um .operador regexp, ou apenas \./como ^está implícito no GNU find) -regexcomo $directoryhavia ..

Você precisaria fazer algo semelhante com $directory, tendo em mente que todos os operadores regexp em $directory( ^$*()+[]?.\...) precisariam ser escapados. Mas aqui você também pode fazer:

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

(Também substituí .por, \.pois suspeito que você deseja corresponder a um literal .e não a qualquer caractere, e removi o ?que não era necessário aqui).

Ou seja, faça com que seu padrão (que aqui é garantido que não abrange um /) corresponda após any /(e até o final do caminho do arquivo, como $também está implícito) em vez de depois de algo que corresponda a $directory.

Com zsh -o extendglobvocê pode fazer:

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

Que tem várias vantagens sobre o GNU find:

  • funcionaria mesmo em sistemas não-GNU (remove a dependência do GNU find)
  • funciona mesmo se $directorycomeçar com-
  • fornece uma lista ordenada
  • in zsh, o que [a-zA-Z0-9]corresponde não é aleatório e não varia com as localidades como in finde corresponde aos caracteres que suponho que você deseja corresponder e somente eles. Em find, você precisaria [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]obter o equivalente.
  • funciona mesmo que $directoryseja um link simbólico para um diretório (você pode adicionar a -Hopção findpara isso).
  • funciona mesmo se os caminhos do arquivo (neste caso, o conteúdo de $directory) contiverem uma sequência de bytes que não formam caracteres válidos no código do idioma atual ( findos 's -regex' .*não puderam corresponder àqueles, pois .correspondem apenas a caracteres válidos).
  • em vez de imprimir essa lista, você pode usá-la diretamente (como argumentos para um comando, para fazer um loop sobre ela, etc.)
  • você também pode usar coisas como (<0-255>~????*)combinar números decimais de 0 a 255 compostos de no máximo 3 dígitos ou (<0-255>~0?*)para aqueles números sem 0 inicial, zshsendo globs uma das poucas APIs de correspondência de padrões que suportam intervalos de correspondência de números.

informação relacionada