Existe um equivalente mais curto a long / path / ** / ^ *. (pattern | complex) ~ long / path / (bad-1 | bad-2) / * (.) que não requer repetição longa /caminho/?

3

É um padrão zh extended glob. O objetivo é combinar todos os arquivos com um padrão em uma hierarquia de diretórios, com exceção de sub-hierarquias específicas. O padrão no título funciona, mas eu queria algo que não exigisse a repetição de long/path/ .

Eu tentei o seguinte:

long/path/(^(bad-1|bad-2)/|)**/^*.(complex|pattern)(.)
long/path/(**~(bad-1|bad-2)/*)/^*.(complex|pattern)(.)

com KSH_GLOB adicionado:

long/path/?(^(bad-1|bad-2)/)**/^*.(complex|pattern)(.)

Todos eles resultam em um erro de padrão ruim. Parece que o problema é ter um / entre parênteses. A documentação diz:

As mentioned above, a '/' used as a directory separator may not appear inside parentheses

Isso me confundiu porque (dir/)# é um bom padrão. Ele é mencionado nos documentos:

A pathname component of the form '(foo/)#' matches a path consisting of zero or more directories matching the pattern foo.

Eu acho que é a exceção.

Para ser claro, estou procurando por equivalentes. Isso exclui:

long/path/^(bad-1|bad-2)/**/^*.(complex|pattern)(.)

pois exclui itens como long/path/good.pattern e

long/path/(^(bad-1|bad-2)/)#/^*.(complex|pattern)(.)
long/path/**/^*.(complex|pattern)~*/(bad-1|bad-2)/*(.)

desde que aqueles excluam coisas como o que está abaixo de long/path/good/bad-1 .

EDIT: Só para mencionar, uma solução não precisa necessariamente usar apenas globbing. Se isso puder ser feito adicionando o uso de chave ou expansão de histórico ou algum outro recurso zsh, isso é ótimo.

EDIT 2: Seguindo minhas próprias idéias, tentei expandir a história:

long/path/**/^*.(complex|pattern)~!{#$:s/\**//}/(bad-1|bad-2)/*(.)

No entanto, isso falhou porque 1) a última palavra da linha atual é a anterior àquela em que a expansão está, e 2) porque a substituição da história parece ser feita após a expansão glob (devo estar entendendo mal alguma coisa aqui porque isso parece ir contra os documentos; talvez todas as expansões sejam feitas com base em palavras por palavra).

Eu também tentei a expansão de chaves:

( IFS=\~; printf "%s\n" long/path/{**/^*.(complex|pattern),(bad-1|bad-2)/*(.)} )

Não funcionou. Os dois padrões globais ainda eram tomados como palavras separadas, em vez de serem unidos em um único padrão. Eu acho que IFS não é levado em consideração aqui. Faz sentido.

Eu também tentei substituição em qualificadores glob:

+/**/^*.(complex|pattern)~+/(bad-1|bad-2)/*(.:s,+,long/path,)

Mas, é claro, isso não funcionaria porque a substituição seria feita depois da correspondência, não antes.

    
por JoL 18.08.2018 / 02:02

2 respostas

3

Entendi! Double slashes para marcar o prefixo:

long/path//**/^*.(complex|pattern)~*//(bad-1|bad-2)/*(.)

Às vezes você não percebe que algo é um recurso até encontrar um uso para ele. Eu não posso acreditar que o fato de que barras contíguas sejam equivalentes a uma pode realmente ser útil. :)

    
por 18.08.2018 / 04:01
0

Os documentos para (...) list / como uma exceção:

Note that grouping cannot extend over multiple directories: it is an error to have a '/' within a group (this only applies for patterns used in filename generation). There is one exception: a group of the form (pat/)# appearing as a complete path segment can match a sequence of directories.

A repetição pode ser evitada usando uma expressão para filtrar os resultados:

% print -l a/**/*(.)
a/b/c/foo/file
a/b/d/foo/file
a/bad/e/foo/file
a/nope/d/foo/file
% print -l a/**/*(.e:'[[ $REPLY != *(bad|nope)* ]]':)
a/b/c/foo/file
a/b/d/foo/file
    
por 18.08.2018 / 03:13

Tags