Alguém sabe como as find
consultas de pesquisa Unix -name com _?
na coluna mais à esquerda se relacionam com Kleene Star conforme definido na Wikipedia ? Como posso realizar as linhas com _?
using find
?
. : empty string, X : cartesian product
-name \A\B Language A X B
-name \ABC Language A X B X C
-name : name at leafs, builds set of string in language
-name \. V^0 {e, ""} language only of the empty string A with only one leg?
-name \? V^1 V language of single characters
-name \???... V^n language of n character strings, concatenates strings in language
-name \* V^* langauge of \cup_{i\gte0} V^i
a? -name \n V^n like \{n\} in grep with integer?
b? -name \*n (V^*)^n language of n words, word can be empty
-name \*\??... (V^*)^n
-name \?\* V^+ langauge of \cup_{i\gte1} V^i
-name \?\*\??... (V^+)^n language of n words, word must have character
Parece que .
é um gráfico A
com apenas uma perna definida com comprimento. grep
usa \{n\}
para a?
, no entanto não consigo encontrar o equivalente com find
.
Os padrões passados para
find
's-name
e-path
(também-iname
e-ipath
em algumasfind
implementações) são os mesmos usados para geração de nome de arquivo, também conhecida como expansão de nome de caminho, ou globbing em shells, e que se originam no/etc/glob
auxiliar que o primeiro shell Unix estava invocando para executar esse processo no início dos anos 70.Normalmente, hoje em dia,
find
as implementações usam a função padrãofnmatch()
que foi introduzida no final dos anos 80, junto comglob()
ewordexp()
para poder trazer esse tipo de operadores de expansão de shell para softwares diferentes de shells.Em globs de shell padrão,
?
corresponde a qualquer caractere único, o equivalente a regexp.
, e*
corresponde a qualquer sequência de caracteres, o equivalente a regexp.*
e[set]
corresponde a qualquer caractere único ou elemento de agrupamento no conjunto fornecido, o mesmo que regex,[set]
exceto que a negação do conjunto é com!
em vez de^
, e é isso.Então, enquanto regexp
*
corresponde à estrela de Kleen,fnmatch()
's*
não. É a estrela de Kleen aplicada a?
(um único caractere).Ksh88 introduziu uma série de operadores de globbing estendidos que trouxeram paridade entre eles e regexp:
@(...)
equivalente a regexp estendido(...)
?(...)
equivalente a regexp estendido(...)?
*(...)
equivalente a regexp estendida(...)*
, portanto, à estrela de Kleen.+(...)
equivalente a regexp estendido(...)+
.!(...)
sem um equivalente ERE padrão.|
usado dentro deles para alternância.E ksh93 adicionou mais alguns:
{x,y}(...)
equivalente a ERE(...){x,y}
.&
usado dentro e sem equivalente ERE padrão.~(flags:...)
incluindo coisas como~(E:...)
levar os EREs ao pé da letra.O zsh também adicionou operadores trazendo paridade ao ERE com sintaxe diferente (geralmente mais concisa que no ksh), como:
#
equivalente a ERE*
(estrela de Kleen)##
equivalente a ERE+
(...)
equivalente a ERE(...)
(com|
manipulado dentro para alternância como em ERE)(#cy,y)
equivalente a ERE{x,y}
.Mas nenhum desses operadores ksh ou zsh chegou à especificação padrão da
sh
linguagem (embora ash
linguagem padrão seja baseada principalmente em um subconjunto da linguagem ksh88) nem emfnmatch()
(como usado porfind
's-name
/-path
).As implementações GNU e uClibc de
fnmatch()
no entanto suportam umFNM_EXTMATCH
sinalizador com o qual os operadores de globbing estendidos do ksh88 (incluindo*(...)
) são reconhecidos, mas nenhumafind
implementação que eu conheça usa esse sinalizador para correspondência-name
/-path
. Fazer isso os tornaria não compatíveis com POSIX, como-name '*(foo)'
é necessário para corresponder em arquivos cujo nome termina em(foo)
não aqueles cujo nome é feito de qualquer número defoo
s.Algumas
find
implementações, no entanto, têm um-regex
operador que funciona como-path
exceto que ele pega expressões regulares implicitamente ancoradas em vez de shell globs. O sabor padrão de regex e a sintaxe para alternar entre sabores de regex variam entrefind
implementações (por exemplo, você precisa de uma-E
opção no BSDfind
para alternar para regexps estendidas padrão e um-regextype posix-extended
predicado no GNUfind
em vez disso).Para arquivos cujos nomes são compostos por qualquer número de
foo
s, você faria:Onde esses
*
s correspondem às estrelas de Kleen.Se você está se perguntando como combinar 0 ou 1 ocorrência de
_
em um padrão-name
(fnmatch()
), a resposta é "você não pode".Não há equivalente de
find -E . -regex '.*/foo_?bar'
(sintaxe BSD) equivalente a-name
, mas você sempre pode fazer:Ou use
zsh
o globbing recursivo do :Ou em ksh93 (que
globstar
reconhece o operador glob recursivo do zsh**/
):Ou
bash
5.0+ (queextglob
reconhece operadores ksh88 e com globbing recursivoglobstar
zsh
de**/
):Ou use
perl
o que tem expressões regulares avançadas e umFile::Find
módulo:Há também um
File::FnMatch
módulo perl , onde você pode usarFNM_EXTMATCH
se o sistemafnmatch()
tiver: