Como converter uma string para minúsculas no Bash?

Existe uma maneira no bash para converter uma seqüência de caracteres em uma seqüência de caracteres minúscula?

Por exemplo, se eu tiver:

a="Hi all" 

Eu quero convertê-lo para:

 "hi all" 

Existem várias formas:

tr

 $ echo "$a" | tr '[:upper:]' '[:lower:]' hi all 

AWK

 $ echo "$a" | awk '{print tolower($0)}' hi all 

Bash 4.0

 $ echo "${a,,}" hi all 

sed

 $ echo "$a" | sed -e 's/\(.*\)/\L\1/' hi all # this also works: $ sed -e 's/\(.*\)/\L\1/' < << "$a" hi all 

Perl

 $ echo "$a" | perl -ne 'print lc' hi all 

Festança

 lc(){ case "$1" in [AZ]) 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 

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 compilation)

 $ 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 compilation)

 $ string="a few words" $ declare -c string $ string=$string $ echo "$string" A few words 

Caso de 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 atributo de declare , use + . Por exemplo, declare +c string . Isso afeta as atribuições subsequentes e não o valor atual.

As opções de declare 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 “toggle primeiro caractere por palavra” ( ${var~} ), como sugerido por ghostdog74 .

Editar: Corrigido o comportamento do til para corresponder ao Bash 4.3.

 echo "Hi All" | tr "[:upper:]" "[:lower:]" 

tr :

 a="$(tr [AZ] [az] < << "$a")" 

AWK :

 { print tolower($0) } 

sed :

 y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ 

Eu sei que este é um post antigo, mas eu fiz essa resposta para outro site, então pensei em postar aqui:

UPPER -> lower : use python:

 b=`echo "print '$a'.lower()" | python` 

Ou Ruby:

 b=`echo "print '$a'.downcase" | ruby` 

Ou Perl (provavelmente 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ê tem (e é um pouco louco …):

 b=`echo "console.log('$a'.toLowerCase());" | node` 

Você também pode usar o dd (mas eu não faria!):

 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 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ê tem (e é um pouco louco …):

 b=`echo "console.log('$a'.toUpperCase());" | node` 

Você também pode usar o dd (mas eu não faria!):

 b=`echo "$a" | dd conv=ucase 2> /dev/null` 

Além disso, quando você diz “shell”, eu estou supondo que você quer dizer bash mas se você pode usar zsh é tão fácil quanto

 b=$a:l 

para minúsculas e

 b=$a:u 

para maiúsculas.

Em zsh:

 echo $a:u 

Tenho que amar zsh!

Usando o GNU sed :

 sed 's/.*/\L&/' 

Exemplo:

 $ foo="Some STRIng"; $ foo=$(echo "$foo" | sed 's/.*/\L&/') $ echo "$foo" some string 

Para um shell padrão (sem bashisms) usando somente 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}" } 

Pré Bash 4.0

Bash Abaixe o caso de uma string e atribua a variável

 VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]') echo "$VARIABLE" 

Expressão regular

Eu gostaria de receber o crédito pelo comando que desejo compartilhar, mas a verdade é que o obtive para uso próprio em http://commandlinefu.com . Tem a vantagem que se você cd a qualquer diretório dentro de sua própria pasta de casa que é isto mudará todos os arquivos e pastas para minúsculas recursivamente por favor use com precaução. É uma correção de linha de comando shiny 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 esta solução seja útil. A única coisa que este comando não faz é replace espaços por sublinhados – talvez bem outra hora.

Na bash 4 você pode usar o typeset

Exemplo:

 A="HELLO WORLD" typeset -l A=$A 

Você pode tentar isso

 s="Hello World!" echo $s # Hello World! a=${s,,} echo $a # hello world! b=${s^^} echo $b # HELLO WORLD! 

insira a descrição da imagem aqui

ref: http://wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/

Se estiver usando v4, isso é ativado . Se não, aqui está uma solução simples e amplamente aplicável . Outras respostas (e comentários) neste tópico foram muito ú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:

  • Fazendo: a="Hi All" e depois: lcase a fará o mesmo que: a=$( echolcase "Hi All" )
  • Na function lcase, usar ${!1//\'/"'\''"} vez de ${!1} permite que isso funcione mesmo quando a string tiver aspas.

Para versões Bash anteriores a 4.0, esta versão deve ser mais rápida (já que 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 [AZ] ) 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 tenha funcionado corretamente para mim.

Apesar de quantos anos esta questão é e semelhante a esta resposta pelo technosaurus . Eu tive dificuldade em encontrar uma solução que fosse portátil na maioria das plataformas (That I Use), bem como versões mais antigas do bash. Eu também tenho sido frustrado com matrizes, funções e uso de impressões, ecos e arquivos temporários para recuperar variables ​​triviais. Isso funciona muito bem para mim até agora eu pensei que iria compartilhar. Meus principais ambientes de teste são:

  1. GNU bash, versão 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
  2. GNU bash, versão 3.2.57 (1) -release (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 for loop para iterar pelas strings. Para a linha abaixo, se você não viu nada assim antes disso, aprendi isso . Neste caso, a linha verifica se o caracter $ {input: $ i: 1} (minúsculo) existe na input e, se assim for, o substitui pelo caractere dado $ {ucs: $ j: 1} (maiúscula) e o armazena de volta à input.

 input="${input/${input:$i:1}/${ucs:$j:1}}" 

Muitas respostas usando programas externos, o que não está realmente usando o Bash .

Se você sabe que terá o Bash4 disponível, deve usar apenas a notação ${VAR,,} (é fácil e legal). Para Bash antes de 4 (Meu Mac ainda usa Bash 3.2 por exemplo). Eu usei a versão corrigida da resposta do @ ghostdog74 para criar uma versão mais portátil.

Você pode chamar lowercase 'my STRING' e obter uma versão em minúscula. Eu li comentários sobre como configurar o resultado para um var, mas isso não é realmente portátil no Bash , já que não podemos retornar strings. Imprimi-lo é a melhor solução. Fácil de capturar com algo como var="$(lowercase $str)" .

Como isso funciona

A maneira como isso funciona é obtendo a representação de inteiro ASCII de cada caractere com printf e, em seguida, adding 32 se upper-to->lower ou subtracting 32 se lower-to->upper . Em seguida, use printf novamente para converter o número de volta para um caractere. De '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.
Por favor, note os comentários no código, como eles explicam um monte de coisas:

 #!/bin/bash # lowerupper.sh # Prints the lowercase version of a char lowercaseChar(){ case "$1" in [AZ]) 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 [az]) 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, já que sei que só vou passar caracteres ASCII para ele.
Eu estou usando isso para algumas opções de CLI sem distinção entre maiúsculas e minúsculas, por exemplo.

O caso de conversão é feito apenas para alfabetos. Então, isso deve funcionar perfeitamente.

Estou me concentrando na conversão de alfabetos entre az de maiúsculas para minúsculas. Quaisquer outros caracteres devem ser impressos na stdout como é …

Converte todo o texto em path / to / file / filename dentro do intervalo az para AZ

Para converter letras minúsculas para maiúsculas

 cat path/to/file/filename | tr 'az' 'AZ' 

Para converter de maiúsculas para minúsculas

 cat path/to/file/filename | tr 'AZ' 'az' 

Por exemplo,

nome do arquivo:

 my name is xyz 

é convertido para:

 MY NAME IS XYZ 

Exemplo 2:

 echo "my name is 123 karthik" | tr 'az' 'AZ' # Output: # MY NAME IS 123 KARTHIK 

Exemplo 3:

 echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'az' 'AZ' # Output: # MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK 

Para armazenar a string transformada em uma variável. A seguir funcionou para mim – $SOURCE_NAME para $TARGET_NAME

 TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`" 

Essa é uma variação muito mais rápida da abordagem do JaredTS486 que usa resources nativos do Bash (incluindo versões do Bash <4.0) para otimizar sua abordagem.

Eu cronometrei 1.000 iterações dessa abordagem para uma pequena cadeia (25 caracteres) e uma cadeia maior (445 caracteres), ambas para conversões em maiúsculas e minúsculas. Como as strings de teste são predominantemente minúsculas, as conversões para minúsculas são geralmente mais rápidas do que para maiúsculas.

Eu 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 que a do tr em vários casos.

Aqui estão os resultados de tempo para 1.000 iterações de 25 caracteres:

  • 0,46s para minha abordagem em minúsculas; 0,96 para maiúsculas
  • 1.16s para a abordagem de Orwellophile para minúsculas; 1,59s para maiúsculas
  • 3,67s para tr para minúsculas; 3,81s para maiúsculas
  • 11.12s para a abordagem do ghostdog74 para minúsculas; 31.41 para maiúsculas
  • 26.25s para a abordagem do technosaurus em minúsculas; 26.21s para maiúsculas
  • 25.06s para a abordagem do JaredTS486 para minúsculas; 27.04s para maiúsculas

Resultados de tempo para 1.000 iterações de 445 caracteres (consistindo no poema “The Robin” de Witter Bynner):

  • 2s para minha abordagem em minúsculas; 12s para maiúsculas
  • 4s para tr para minúsculas; 4s para maiúsculas
  • 20s para a abordagem de Orwellophile para minúsculas; 29s para maiúsculas
  • 75s para a abordagem do ghostdog74 para minúsculas; 669s para maiúsculas. É interessante notar quão dramática é a diferença de desempenho entre um teste com partidas predominantes vs. um teste com erros predominantes
  • 467s para a abordagem do technosaurus em minúsculas; 449s para maiúsculas
  • 660s para a abordagem do JaredTS486 para minúsculas; 660s para maiúsculas. É interessante notar que essa abordagem gerou falhas de página contínuas (troca de memory) no Bash

Solução:

 #!/bin/bash set -e set -u declare LCS="abcdefghijklmnopqrstuvwxyz" declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ" function lcase() { local TARGET="${1-}" local UCHAR='' local UOFFSET='' while [[ "${TARGET}" =~ ([AZ]) ]] 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}" =~ ([az]) ]] 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 input contém as letras maiúsculas restantes, encontre a próxima e substitua todas as ocorrências dessa letra pela sua variante em minúsculas. Repita até que todas as letras maiúsculas sejam substituídas.

Algumas características de desempenho da minha solução:

  1. Usa apenas utilitários internos do shell, o que evita a sobrecarga de invocar utilitários binários externos em um novo processo
  2. Evita sub-shells, que incorrem em penalidades de desempenho
  3. Usa mecanismos de shell que são compilados e otimizados para desempenho, como substituição de cadeia global em variables, ajuste de sufixos variables ​​e pesquisa e correspondência de regex. Estes mecanismos são muito mais rápidos do que iterar manualmente através de strings
  4. Repete apenas o número de vezes necessário para a contagem de caracteres exclusivos correspondentes a serem convertidos. Por exemplo, a conversão de uma cadeia que possui três caracteres maiúsculos diferentes para minúsculas requer apenas três iterações de loop. Para o alfabeto ASCII pré-configurado, o número máximo de iterações de loop é 26
  5. UCS e LCS podem ser aumentados com caracteres adicionais