Apesar de ser mais complexo do que a resposta melhor pontuada, esta realmente faz exatamente isso: 'primeiro caractere maiúsculo de uma variável'. A resposta com melhor pontuação não possui esses resultados. Parece que respostas simples são votadas com mais vontade do que as corretas?
Krzysztof Jabłoński 26/02
15
@ KrzysztofJabłoński: Na verdade, a "resposta mais bem classificada" abaixo produzirá os mesmos resultados que esta resposta no Bash 4. Essa resposta tem a sobrecarga de chamar um subshell (outro shell), a sobrecarga de chamar o utilitário 'tr' (outro processo , não Bash), a sobrecarga do uso de aqui-doc / string (criação temporária de arquivo) e usa duas substituições em comparação com a resposta com a melhor pontuação. Se você absolutamente precisar escrever código legado, considere usar uma função em vez de um subshell.
Steve Steve
2
Esta resposta assume que a entrada está em letras minúsculas. Esta variante não possui suposições: $ (tr '[: lower:]' '[: upper:]' <<< $ {foo: 0: 1}) $ (tr '[: upper:]' '[: lower: ] '<<< $ {foo: 1})
Itai Hanski
5
@ItaiHanski O OP não especificou o que deveria acontecer com os personagens restantes, apenas o primeiro. Supunha que queria mudar notQuiteCamelem NotQuiteCamel. Sua variante tem o efeito colateral ou força o restante a minúsculo - ao custo de dobrar o número de subcascas e processos tr.
Jesse Chisholm
3
@DanieleOrlando, é verdade, mas esta pergunta não tem tags além de bash.
@CMCDragonkai: Para minúscula a primeira letra, use "${foo,}". Para minúsculas todas as letras, use "${foo,,}". Para colocar todas as letras em maiúsculas, use "${foo^^}".
Steve
1
Eu notei isso acidentalmente ${foo~}e ${foo~~}tem o mesmo efeito que ${foo^}e ${foo^^}. Mas nunca vi essa alternativa mencionada em nenhum lugar.
mivk
5
isso parece não funcionar em Macs. recebendo o seguinte erro:bad substitution
Toland Hon
1
@TolandHon: Como você provavelmente já trabalhou, precisará atualizar para a versão 4.x ou tentar outra solução se essa máquina não puder ser atualizada por algum motivo.
não funciona no MacOS10 Lion sed, suspiro, o \ u se expande para u em vez de ser um operador.
vwvan
2
@vwvan brew install coreutils gnu-sede siga as instruções para usar os comandos sem o prefixo g. Pelo que vale a pena, eu nunca quis executar a versão OSX desses comandos desde a obtenção das versões GNU.
Dean
@vwvan: Sim, desculpe, você vai precisar GNU sedneste caso
Steve
2
@Dean: FWIW, eu nunca quis correr OSX :-)
Steve
5
Apenas mude para sed 's/./\U&/e ele funcionará no POSIX sed.
finalmente algo que funciona com uma variável e no Mac! Obrigado!
OZZIE
4
@DanieleOrlando, não tão portátil quanto se poderia esperar. tr [:lower:] [:upper:]é uma escolha melhor se precisar trabalhar em idiomas / localidades que incorporem letras que não estão nos intervalos a-zou A-Z.
Isso também pode ser feito no bash puro com o bash-3.2:
# First, get the first character.
fl=${foo:0:1}# Safety check: it must be a letter :).if[[ ${fl}==[a-z]]];then# Now, obtain its octal value using printf (builtin).
ord=$(printf '%o'"'${fl}")# Fun fact: [a-z] maps onto 0141..0172. [A-Z] is 0101..0132.# We can use decimal '- 40' to get the expected result!
ord=$(( ord -40))# Finally, map the new value back to a character.
fl=$(printf '%b''\'${ord})
fi
echo "${fl}${foo:1}"
como definir foo? Eu tentei, foo = $1mas só consigo-bash: foo: command not found
OZZIE
1
@OZZIE, não há espaços ao redor das =tarefas. Isso é algo que o shellcheck.net encontrará para você programaticamente.
Charles Duffy
Eu sempre esqueço que cerca de shell scripts .. única língua onde um espaço (antes / depois) questões ... suspirar (python é pelo menos 4 se bem me lembro)
OZZIE
@OZZIE, ele tem à matéria, porque se ele não importa, você não poderia passar =como um argumento para um programa (como é suposto saber se someprogram =está em execução someprogram, ou atribuir a uma variável chamada someprogram?)
Por favor, escreva um código mais limpo! faltam citações em todo o lugar. Você está usando sintaxe obsoleta (backticks); você está usando sintaxe antiquada ( $[...]). Você está usando muitos parênteses inúteis. Você está assumindo que a sequência consiste em caracteres do alfabeto latino (que tal letras acentuadas ou em outros alfabetos?). Você tem muito trabalho para tornar esse trecho utilizável! (e como você está usando regex, você pode usá-lo para encontrar a primeira letra, em vez de um loop).
91117 Gnourf_gniourf
6
Eu acho que você está errado. É o comentário obrigatório que acompanha o voto negativo, explicando todos os padrões e conceitos errados da resposta. Por favor, aprenda com seus erros (e antes disso, tente entendê-los) em vez de ser teimoso. Ser um bom companheiro também é incompatível com a disseminação de más práticas.
911717 Gnourf_gniourf # 94417
1
Ou, se você estiver usando o Bash ≥4, não precisará tr:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf
5
Este código ainda está muito quebrado. Ainda está usando backticks em vez da sintaxe de substituição moderna; ele ainda possui aspas incomparáveis; ainda faltam citações em lugares onde elas realmente importam ; etc. Tente colocar alguns caracteres glob cercados de espaço em branco em seus dados de teste, se você não acredita que essas aspas ausentes façam diferença, e corrija os problemas encontrados pelo shellcheck.net até que esse código seja limpo.
Charles Duffy
2
Quanto ao idioma que você citou em unix.stackexchange.com/questions/68694/… , o que você sente falta é que echo $fooé um exemplo de uma situação em que o analisador espera uma lista de palavras ; Assim, no seu echo ${F}, o conteúdo de Fé dividido por cadeias e expandido por glob. O mesmo se aplica ao echo ${S:$N:1}exemplo e a todo o resto. Veja BashPitfalls # 14 .
Respostas:
fonte
notQuiteCamel
emNotQuiteCamel
. Sua variante tem o efeito colateral ou força o restante a minúsculo - ao custo de dobrar o número de subcascas e processos tr.bash
.Uma maneira com o bash (versão 4+):
impressões:
fonte
"${foo,}"
. Para minúsculas todas as letras, use"${foo,,}"
. Para colocar todas as letras em maiúsculas, use"${foo^^}"
.${foo~}
e${foo~~}
tem o mesmo efeito que${foo^}
e${foo^^}
. Mas nunca vi essa alternativa mencionada em nenhum lugar.bad substitution
Uma maneira com
sed
:Impressões:
fonte
brew install coreutils gnu-sed
e siga as instruções para usar os comandos sem o prefixog
. Pelo que vale a pena, eu nunca quis executar a versão OSX desses comandos desde a obtenção das versões GNU.sed
neste casosed 's/./\U&/
e ele funcionará no POSIX sed.fonte
Aqui está a maneira "nativa" das ferramentas de texto:
fonte
tr [:lower:] [:upper:]
é uma escolha melhor se precisar trabalhar em idiomas / localidades que incorporem letras que não estão nos intervalosa-z
ouA-Z
.Usando apenas awk
fonte
Isso também pode ser feito no bash puro com o bash-3.2:
fonte
foo = $1
mas só consigo-bash: foo: command not found
=
tarefas. Isso é algo que o shellcheck.net encontrará para você programaticamente.=
como um argumento para um programa (como é suposto saber sesomeprogram =
está em execuçãosomeprogram
, ou atribuir a uma variável chamadasomeprogram
?)Isso funciona também ...
E assim por diante.
Fontes:
Introduções / Tutoriais:
fonte
Para colocar em maiúscula apenas a primeira palavra:
Para colocar em maiúscula todas as palavras na variável:
(funciona no bash 4+)
fonte
foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done)
Resolução mais curta para cada palavra. foo Agora é "um dois três"Solução alternativa e limpa para Linux e OSX, também pode ser usada com variáveis bash
retorna Abc
fonte
Este funcionou para mim:
Procurando por todos os arquivos * php no diretório atual e substitua o primeiro caractere de cada nome de arquivo por letra maiúscula:
por exemplo: test.php => Test.php
fonte
apenas por diversão, aqui está você:
fonte
Não é exatamente o que pediu, mas é bastante útil
E o oposto
fonte
primeira letra para abaixar xc () {v-primeira letra para abaixar | xclip -selection clipboard}
fonte
E se o primeiro caractere não for uma letra (mas uma tabulação, espaço e aspas duplas)? É melhor testá- lo até encontrarmos uma carta! Assim:
fonte
$[...]
). Você está usando muitos parênteses inúteis. Você está assumindo que a sequência consiste em caracteres do alfabeto latino (que tal letras acentuadas ou em outros alfabetos?). Você tem muito trabalho para tornar esse trecho utilizável! (e como você está usando regex, você pode usá-lo para encontrar a primeira letra, em vez de um loop).tr
:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
echo $foo
é um exemplo de uma situação em que o analisador espera uma lista de palavras ; Assim, no seuecho ${F}
, o conteúdo deF
é dividido por cadeias e expandido por glob. O mesmo se aplica aoecho ${S:$N:1}
exemplo e a todo o resto. Veja BashPitfalls # 14 .