Respostas:
Existem várias maneiras:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
Você pode ter problemas de portabilidade com os seguintes exemplos:
$ echo "${a,,}"
hi all
$ echo "$a" | sed -e 's/\(.*\)/\L\1/'
hi all
# this also works:
$ sed -e 's/\(.*\)/\L\1/' <<< "$a"
hi all
$ echo "$a" | perl -ne 'print lc'
hi all
lc(){
case "$1" in
[A-Z])
n=$(printf "%d" "'$1")
n=$((n+32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
word="I Love Bash"
for((i=0;i<${#word};i++))
do
ch="${word:$i:1}"
lc "$ch"
done
Nota: YMMV neste. Não funciona para mim (versão 4.2.46 e 4.0.33 do GNU bash (e o mesmo comportamento 2.05b.0 mas o nocasematch não está implementado)) mesmo com o uso shopt -u nocasematch;
. Desativar esse nocasematch faz com que [["fooBaR" == "FOObar"]] corresponda a OK, mas por dentro, estranhamente, [bz] é incorretamente correspondido por [AZ]. Bash é confundido com o duplo negativo ("nocasematch desestabilizador")! :-)
word="Hi All"
os outros exemplos, ele retornará ha
, não hi all
. Funciona apenas para as letras maiúsculas e pula as letras já em minúsculas.
tr
e awk
são especificados no padrão POSIX.
tr '[:upper:]' '[:lower:]'
usará o código do idioma atual para determinar equivalentes em maiúsculas / minúsculas, portanto, ele funcionará com códigos de idioma que usam letras com marcas diacríticas.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
No Bash 4:
Para minúsculas
$ string="A FEW WORDS"
$ echo "${string,}"
a FEW WORDS
$ echo "${string,,}"
a few words
$ echo "${string,,[AEIUO]}"
a FeW WoRDS
$ string="A Few Words"
$ declare -l string
$ string=$string; echo "$string"
a few words
Para maiúsculas
$ string="a few words"
$ echo "${string^}"
A few words
$ echo "${string^^}"
A FEW WORDS
$ echo "${string^^[aeiou]}"
A fEw wOrds
$ string="A Few Words"
$ declare -u string
$ string=$string; echo "$string"
A FEW WORDS
Alternar (não documentado, mas opcionalmente configurável em tempo de compilação)
$ string="A Few Words"
$ echo "${string~~}"
a fEW wORDS
$ string="A FEW WORDS"
$ echo "${string~}"
a FEW WORDS
$ string="a few words"
$ echo "${string~}"
A few words
Capitalizar (não documentado, mas opcionalmente configurável em tempo de compilação)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Caso do título:
$ string="a few words"
$ string=($string)
$ string="${string[@]^}"
$ echo "$string"
A Few Words
$ declare -c string
$ string=(a few words)
$ echo "${string[@]}"
A Few Words
$ string="a FeW WOrdS"
$ string=${string,,}
$ string=${string~}
$ echo "$string"
A few words
Para desativar um declare
atributo, use +
. Por exemplo declare +c string
,. Isso afeta as atribuições subseqüentes e não o valor atual.
As declare
opções alteram o atributo da variável, mas não o conteúdo. As reatribuições nos meus exemplos atualizam o conteúdo para mostrar as alterações.
Editar:
Adicionado "alternar o primeiro caractere pela palavra" ( ${var~}
), como sugerido por ghostdog74 .
Edit: Corrigido o comportamento do til para coincidir com o Bash 4.3.
string="łódź"; echo ${string~~}
, retornará "ŁÓDŹ", mas echo ${string^^}
retornará "łóDź". Mesmo em LC_ALL=pl_PL.utf-8
. Isso está usando o bash 4.2.24.
en_US.UTF-8
. É um bug e eu relatei.
echo "$string" | tr '[:lower:]' '[:upper:]'
. Provavelmente exibirá a mesma falha. Portanto, o problema não é, pelo menos em parte, o de Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr
não funciona para mim para caracteres que não são da ACII. Eu tenho o conjunto de localizações correto e os arquivos de localidade gerados. Tem alguma idéia do que eu poderia estar fazendo de errado?
[:upper:]
necessário?
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"
parece mais fácil para mim. Eu ainda sou um iniciante ...
sed
solução; Eu tenho trabalhado em um ambiente que por algum motivo não tem tr
, mas eu ainda tenho que encontrar um sistema, sem sed
, além de uma grande parte do tempo que eu quero fazer isso eu acabei de fazer outra coisa em sed
qualquer maneira para cadeia de lata os comandos juntos em uma única instrução (longa).
tr [A-Z] [a-z] A
, o shell pode executar a expansão do nome do arquivo se houver nomes de arquivos consistindo em uma única letra ou se o nullgob estiver definido. tr "[A-Z]" "[a-z]" A
se comportará corretamente.
sed
tr [A-Z] [a-z]
está incorreto em quase todos os locais. por exemplo, na en-US
localidade, A-Z
é realmente o intervalo AaBbCcDdEeFfGgHh...XxYyZ
.
Eu sei que este é um post antigo, mas eu respondi para outro site, então pensei em publicá-lo aqui:
UPPER -> lower : use python:
b=`echo "print '$a'.lower()" | python`
Ou Ruby:
b=`echo "print '$a'.downcase" | ruby`
Ou Perl (provavelmente o meu favorito):
b=`perl -e "print lc('$a');"`
Ou PHP:
b=`php -r "print strtolower('$a');"`
Ou Awk:
b=`echo "$a" | awk '{ print tolower($1) }'`
Ou Sed:
b=`echo "$a" | sed 's/./\L&/g'`
Ou Bash 4:
b=${a,,}
Ou NodeJS, se você o tiver (e estiver um pouco louco ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Você também pode usar dd
(mas eu não usaria!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
inferior -> SUPERIOR :
use python:
b=`echo "print '$a'.upper()" | python`
Ou Ruby:
b=`echo "print '$a'.upcase" | ruby`
Ou Perl (provavelmente o meu favorito):
b=`perl -e "print uc('$a');"`
Ou PHP:
b=`php -r "print strtoupper('$a');"`
Ou Awk:
b=`echo "$a" | awk '{ print toupper($1) }'`
Ou Sed:
b=`echo "$a" | sed 's/./\U&/g'`
Ou Bash 4:
b=${a^^}
Ou NodeJS, se você o tiver (e estiver um pouco louco ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Você também pode usar dd
(mas eu não usaria!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Além disso, quando você diz 'shell', estou assumindo que você quer dizer, bash
mas se você pode usá- zsh
lo, é tão fácil quanto
b=$a:l
para minúsculas e
b=$a:u
para maiúsculas.
a
contiver uma aspas simples, você não apenas terá um comportamento defeituoso, mas um sério problema de segurança.
No zsh:
echo $a:u
Conseguiu amar o zsh!
echo ${(C)a} #Upcase the first char only
Pre Bash 4.0
Bash Abaixe a caixa de uma string e atribua à variável
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echo
tubos: use$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Para um shell padrão (sem bashisms) usando apenas builtins:
uppers=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lowers=abcdefghijklmnopqrstuvwxyz
lc(){ #usage: lc "SOME STRING" -> "some string"
i=0
while ([ $i -lt ${#1} ]) do
CUR=${1:$i:1}
case $uppers in
*$CUR*)CUR=${uppers%$CUR*};OUTPUT="${OUTPUT}${lowers:${#CUR}:1}";;
*)OUTPUT="${OUTPUT}$CUR";;
esac
i=$((i+1))
done
echo "${OUTPUT}"
}
E para maiúsculas:
uc(){ #usage: uc "some string" -> "SOME STRING"
i=0
while ([ $i -lt ${#1} ]) do
CUR=${1:$i:1}
case $lowers in
*$CUR*)CUR=${lowers%$CUR*};OUTPUT="${OUTPUT}${uppers:${#CUR}:1}";;
*)OUTPUT="${OUTPUT}$CUR";;
esac
i=$((i+1))
done
echo "${OUTPUT}"
}
${var:1:1}
são um Bashism.
Você pode tentar isso
s="Hello World!"
echo $s # Hello World!
a=${s,,}
echo $a # hello world!
b=${s^^}
echo $b # HELLO WORLD!
ref: http://wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/
Gostaria de receber o crédito pelo comando que desejo compartilhar, mas a verdade é que eu o obtive para meu próprio uso em http://commandlinefu.com . Tem a vantagem de que, se você cd
acessar um diretório dentro de sua própria pasta pessoal, ele alterará todos os arquivos e pastas para minúsculas recursivamente, use com cuidado. É uma correção de linha de comando brilhante e especialmente útil para as multidões de álbuns que você armazenou em sua unidade.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Você pode especificar um diretório no lugar do ponto (.) Após a localização, que indica o diretório atual ou o caminho completo.
Espero que essa solução seja útil. A única coisa que esse comando não faz é substituir espaços por sublinhados - bem, talvez outra hora.
prename
de perl
: dpkg -S "$(readlink -e /usr/bin/rename)"
dáperl: /usr/bin/prename
Muitas respostas usando programas externos, o que realmente não está sendo usado Bash
.
Se você sabe que terá o Bash4 disponível, use realmente a ${VAR,,}
notação (é fácil e legal). Para o Bash anterior a 4 (meu Mac ainda usa o Bash 3.2, por exemplo). Usei a versão corrigida da resposta de @ ghostdog74 para criar uma versão mais portátil.
Você pode ligar lowercase 'my STRING'
e obter uma versão em minúscula. Eu li comentários sobre como definir o resultado como um var, mas isso não é realmente portátil Bash
, pois não podemos retornar strings. Imprimir é a melhor solução. Fácil de capturar com algo parecido var="$(lowercase $str)"
.
Como isso funciona
A maneira como isso funciona é obtendo a representação inteira ASCII de cada caractere com printf
e então adding 32
se upper-to->lower
, ou subtracting 32
se lower-to->upper
. Em seguida, use printf
novamente para converter o número novamente em um caractere. Desde 'A' -to-> 'a'
temos uma diferença de 32 caracteres.
Usando printf
para explicar:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
E esta é a versão de trabalho com exemplos.
Observe os comentários no código, pois eles explicam muitas coisas:
#!/bin/bash
# lowerupper.sh
# Prints the lowercase version of a char
lowercaseChar(){
case "$1" in
[A-Z])
n=$(printf "%d" "'$1")
n=$((n+32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
# Prints the lowercase version of a sequence of strings
lowercase() {
word="$@"
for((i=0;i<${#word};i++)); do
ch="${word:$i:1}"
lowercaseChar "$ch"
done
}
# Prints the uppercase version of a char
uppercaseChar(){
case "$1" in
[a-z])
n=$(printf "%d" "'$1")
n=$((n-32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
# Prints the uppercase version of a sequence of strings
uppercase() {
word="$@"
for((i=0;i<${#word};i++)); do
ch="${word:$i:1}"
uppercaseChar "$ch"
done
}
# The functions will not add a new line, so use echo or
# append it if you want a new line after printing
# Printing stuff directly
lowercase "I AM the Walrus!"$'\n'
uppercase "I AM the Walrus!"$'\n'
echo "----------"
# Printing a var
str="A StRing WITH mixed sTUFF!"
lowercase "$str"$'\n'
uppercase "$str"$'\n'
echo "----------"
# Not quoting the var should also work,
# since we use "$@" inside the functions
lowercase $str$'\n'
uppercase $str$'\n'
echo "----------"
# Assigning to a var
myLowerVar="$(lowercase $str)"
myUpperVar="$(uppercase $str)"
echo "myLowerVar: $myLowerVar"
echo "myUpperVar: $myUpperVar"
echo "----------"
# You can even do stuff like
if [[ 'option 2' = "$(lowercase 'OPTION 2')" ]]; then
echo "Fine! All the same!"
else
echo "Ops! Not the same!"
fi
exit 0
E os resultados depois de executar isso:
$ ./lowerupper.sh
i am the walrus!
I AM THE WALRUS!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
myLowerVar: a string with mixed stuff!
myUpperVar: A STRING WITH MIXED STUFF!
----------
Fine! All the same!
Isso deve funcionar apenas para caracteres ASCII .
Para mim, tudo bem, pois sei que só passarei caracteres ASCII para ele.
Estou usando isso para algumas opções de CLI que não diferenciam maiúsculas de minúsculas, por exemplo.
A conversão de maiúsculas e minúsculas é feita apenas para alfabetos. Portanto, isso deve funcionar perfeitamente.
Estou focando na conversão de alfabetos entre az de maiúsculas para minúsculas. Quaisquer outros caracteres devem ser impressos apenas em stdout, pois são ...
Converte todo o texto no caminho / para / arquivo / nome do arquivo dentro do intervalo de az para AZ
Para converter letras minúsculas em maiúsculas
cat path/to/file/filename | tr 'a-z' 'A-Z'
Para converter de maiúsculas para minúsculas
cat path/to/file/filename | tr 'A-Z' 'a-z'
Por exemplo,
nome do arquivo:
my name is xyz
é convertido em:
MY NAME IS XYZ
Exemplo 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Exemplo 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Se estiver usando v4, este é cozido-in . Caso contrário, aqui está uma solução simples e amplamente aplicável . Outras respostas (e comentários) sobre este tópico foram bastante úteis na criação do código abaixo.
# Like echo, but converts to lowercase
echolcase () {
tr [:upper:] [:lower:] <<< "${*}"
}
# Takes one arg by reference (var name) and makes it lowercase
lcase () {
eval "${1}"=\'$(echo ${!1//\'/"'\''"} | tr [:upper:] [:lower:] )\'
}
Notas:
a="Hi All"
e então: lcase a
fará a mesma coisa que:a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
vez de ${!1}
permite que isso funcione mesmo quando a string possui aspas.Para versões do Bash anteriores à 4.0, essa versão deve ser mais rápida (pois não bifurca / executa nenhum comando):
function string.monolithic.tolower
{
local __word=$1
local __len=${#__word}
local __char
local __octal
local __decimal
local __result
for (( i=0; i<__len; i++ ))
do
__char=${__word:$i:1}
case "$__char" in
[A-Z] )
printf -v __decimal '%d' "'$__char"
printf -v __octal '%03o' $(( $__decimal ^ 0x20 ))
printf -v __char \\$__octal
;;
esac
__result+="$__char"
done
REPLY="$__result"
}
a resposta do technosaurus também tinha potencial, embora funcionasse corretamente para mim.
Apesar de quantos anos essa pergunta tem e semelhante à resposta do technosaurus . Foi difícil encontrar uma solução que fosse portátil na maioria das plataformas (que eu uso) e nas versões mais antigas do bash. Também fiquei frustrado com matrizes, funções e uso de impressões, ecos e arquivos temporários para recuperar variáveis triviais. Até agora, isso funcionou muito bem para mim e pensei em compartilhar. Meus principais ambientes de teste são:
- Lançamento do GNU bash, versão 4.1.2 (1) (x86_64-redhat-linux-gnu)
- Lançamento do GNU bash, versão 3.2.57 (1) (sparc-sun-solaris2.10)
lcs="abcdefghijklmnopqrstuvwxyz"
ucs="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
input="Change Me To All Capitals"
for (( i=0; i<"${#input}"; i++ )) ; do :
for (( j=0; j<"${#lcs}"; j++ )) ; do :
if [[ "${input:$i:1}" == "${lcs:$j:1}" ]] ; then
input="${input/${input:$i:1}/${ucs:$j:1}}"
fi
done
done
Estilo C simples para loop para iterar pelas seqüências de caracteres. Para a linha abaixo, se você nunca viu nada assim antes, foi aqui que eu aprendi isso . Nesse caso, a linha verifica se o char $ {input: $ i: 1} (minúsculo) existe na entrada e, se houver, substitui-o pelo dado char $ {ucs: $ j: 1} (maiúsculo) e o armazena de volta à entrada.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Essa é uma variação muito mais rápida da abordagem do JaredTS486 que usa recursos nativos do Bash (incluindo versões do Bash <4.0) para otimizar sua abordagem.
Cronometrei 1.000 iterações dessa abordagem para uma sequência pequena (25 caracteres) e uma sequência maior (445 caracteres), tanto para conversões em minúsculas quanto em maiúsculas. Como as sequências de teste são predominantemente em minúsculas, as conversões em minúsculas geralmente são mais rápidas que em maiúsculas.
Comparei minha abordagem com várias outras respostas nesta página que são compatíveis com o Bash 3.2. Minha abordagem é muito mais eficiente do que a maioria das abordagens documentadas aqui e é ainda mais rápida do que tr
em vários casos.
Aqui estão os resultados de temporização para 1.000 iterações de 25 caracteres:
tr
minúsculas; 3.81s para maiúsculasResultados de tempo para 1.000 iterações de 445 caracteres (consistindo no poema "The Robin" de Witter Bynner):
tr
minúsculas; 4s para maiúsculasSolução:
#!/bin/bash
set -e
set -u
declare LCS="abcdefghijklmnopqrstuvwxyz"
declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
function lcase()
{
local TARGET="${1-}"
local UCHAR=''
local UOFFSET=''
while [[ "${TARGET}" =~ ([A-Z]) ]]
do
UCHAR="${BASH_REMATCH[1]}"
UOFFSET="${UCS%%${UCHAR}*}"
TARGET="${TARGET//${UCHAR}/${LCS:${#UOFFSET}:1}}"
done
echo -n "${TARGET}"
}
function ucase()
{
local TARGET="${1-}"
local LCHAR=''
local LOFFSET=''
while [[ "${TARGET}" =~ ([a-z]) ]]
do
LCHAR="${BASH_REMATCH[1]}"
LOFFSET="${LCS%%${LCHAR}*}"
TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}"
done
echo -n "${TARGET}"
}
A abordagem é simples: enquanto a string de entrada tem letras maiúsculas restantes, localize a próxima e substitua todas as instâncias dessa letra por sua variante minúscula. Repita até que todas as letras maiúsculas sejam substituídas.
Algumas características de desempenho da minha solução:
UCS
e LCS
pode ser aumentado com caracteres adicionais