Tenho um makefile com este comando que converte nomes de pastas ./cmd/
de snake_case
paraPascalCase
test:
@for f in $(shell ls ./cmd/); do \
echo $${f}; \
echo $${f} | sed -r 's/(^|_)([a-z])/\U\2/g'; \
done
O que obtenho quando o executo é, com uma letra maiúscula prefixada U
:
api_get_manual
UapiUgetUmanual
E o que espero obter:
ApiGetManual
\U
, como-r
(para o qual-E
agora é o equivalente padrão) é uma extensão não padrão da implementação GNU desed
, inspirada emex
/vi
, também encontrada emperl
, não encontrada em muitas outras implementações.Aqui, em vez disso, você poderia fazer:
Usando:
cmd/*(N:t)
para expandir o glob deN
forma ullglob, obtendo ot
ail de cada expansão.${(C)var}
para colocar palavras em maiúscula na variável${var//_}
à la ksh para remover_
caracteres posteriormenteprint -rl --
para imprimirr
aw eml
linhas separadas.Observe que os nomes dos arquivos são decodificados em texto e convertidos para letras maiúsculas de acordo com a localidade do usuário (categoria LC_CTYPE).
O exemplo acima, para cada sequência de um ou mais caracteres alfanuméricos, converte o primeiro caractere para maiúsculas e todos os demais para minúsculas, além de remover todos os sublinhados.
Uma abordagem mais próxima da sua é remover apenas os sublinhados seguidos por uma letra minúscula (e converter somente essa letra para maiúscula, deixando o resto intacto):
Onde
(#b)
é ativar referências posteriores, para que grupos de captura possam ser referenciados na$match
matriz na substituição(#s)
paras
torta, o equivalente a regex^
[[:lower:]]
corresponde a caracteres classificados como minúsculos, como em expressões regulares.[a-z]
para restringir àqueles entrea
ez
que emzsh
é feito com base no valor do ponto de código, portanto limitado a abcdefghijklmnopqrstuvwxyz$var:u
para converter para maiúsculas como em csh, respeitando o idioma.Sem
zsh
:Assume apenas letras ASCII (
stéphane
seria alterado para,StéPhane
por exemplo, poisé
não é reconhecido como uma letra).Ou como na sua abordagem:
Se limitado a utilitários POSIX, você pode usar
awk
para fazer a capitalização:Assim como o zsh, ele respeitará o idioma para decodificar nomes de arquivos como texto, classificando caracteres
alnum
e convertendo-os para letras maiúsculas.Para combinar com sua abordagem:
Algumas outras notas:
$(shell ...)
é expandido pormake
para o código que foi passado sem qualquer tipo de sanitização, portanto, não funcionará para nomes de arquivo que contenham caracteres especiais na sintaxe do shell, como espaço,;
,*
,'
etc. Na verdade, esse é um caso típico de vulnerabilidade de execução arbitrária de código. Mas, por outro lado, ao usar,make
você precisa desistir e esperar fazer qualquer coisa com segurança ou confiabilidade. Ele só deve ser usado com dados estritamente controlados (aqui pode ser adequado se você puder garantir que ocmd
diretório conterá apenas os arquivos que você espera).echo
não pode ser usado para dados arbitrárioszsh
, incluindosh
o shell padrão paramake
, expansões de parâmetros devem ser colocadas entre aspas para evitar split+glob, então$${f}
deve ser assim"$$f"
(ou"$${f}"
se preferir).Seu comentário nos diz que:
\U
.Em vez de depender do GNU sed, você pode fazer isso usando qualquer awk em qualquer shell em qualquer máquina Unix:
Aqui está o exemplo acima sendo executado em alguma entrada que não é abordada no exemplo da pergunta, para que você possa decidir se a saída é desejável ou não:
Para usar qualquer um dos itens acima em um Makefile
$0
é preciso tornar-se$$0
e o script awk tem que logicamente estar todos em uma linha, então você precisa adicionar alguns;
s e escapar as novas linhas dentro do script, por exemplo (não testado):