¿Cómo convertir una cadena a minúsculas en Bash?

Respuestas:

2182

Hay varias formas:

POSIX estándar

tr

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

AWK

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

No POSIX

Puede encontrar problemas de portabilidad con los siguientes ejemplos:

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

Golpetazo

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 en este caso. No funciona para mí (GNU bash versión 4.2.46 y 4.0.33 (y el mismo comportamiento 2.05b.0 pero no se implementa nocasematch)) incluso con el uso shopt -u nocasematch;. Si se establece que nocasematch hace que [["fooBaR" == "FOObar"]] coincida con OK, pero dentro de mayúsculas y minúsculas [bz] coinciden incorrectamente con [AZ]. ¡Bash se confunde con el doble negativo ("nocasematch")! :-)

ghostdog74
fuente
99
¿Me estoy perdiendo algo o tu último ejemplo (en Bash) realmente hace algo completamente diferente? Funciona para "ABX", pero si en cambio haces word="Hi All"como los otros ejemplos, regresa ha, no hi all. Solo funciona para las letras mayúsculas y omite las letras minúsculas.
Jangosteve
26
Tenga en cuenta que solo los ejemplos try awkse especifican en el estándar POSIX.
Richard Hansen
178
tr '[:upper:]' '[:lower:]'usará la configuración regional actual para determinar equivalentes en mayúsculas / minúsculas, por lo que funcionará con configuraciones regionales que usan letras con signos diacríticos.
Richard Hansen
10
¿Cómo se obtiene la salida en una nueva variable? Es decir, quiero la cadena en minúsculas en una nueva variable?
Adam Parkin
6060
@Adam:b="$(echo $a | tr '[A-Z]' '[a-z]')"
Tino
435

En Bash 4:

En 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

A mayú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

Toggle (no documentado, pero opcionalmente configurable en tiempo de compilación)

$ 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 (indocumentado, pero opcionalmente configurable en tiempo de compilación)

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

Titulo del caso:

$ 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 desactivar un declareatributo, use +. Por ejemplo, declare +c string. Esto afecta las asignaciones posteriores y no el valor actual.

Las declareopciones cambian el atributo de la variable, pero no los contenidos. Las reasignaciones en mis ejemplos actualizan los contenidos para mostrar los cambios.

Editar:

Se agregó "alternar el primer carácter por palabra" ( ${var~}) como lo sugiere ghostdog74 .

Editar: Se corrigió el comportamiento de tilde para que coincida con Bash 4.3.

Pausado hasta nuevo aviso.
fuente
55
Bastante bizzare, los operadores "^^" y ",," no funcionan en caracteres que no son ASCII pero "~~" sí ... Entonces string="łódź"; echo ${string~~}devolverá "ŁÓDŹ", pero echo ${string^^}devuelve "łóDź". Incluso en LC_ALL=pl_PL.utf-8. Eso está usando bash 4.2.24.
Hubert Kario
2
@HubertKario: Eso es raro. Es lo mismo para mí en Bash 4.0.33 con la misma cadena en_US.UTF-8. Es un error y lo he informado.
Pausado hasta nuevo aviso.
1
@HubertKario: Intenta echo "$string" | tr '[:lower:]' '[:upper:]'. Probablemente exhibirá la misma falla. Entonces, el problema no es al menos en parte de Bash.
Pausado hasta nuevo aviso.
1
@DennisWilliamson: Sí, también lo he notado (ver el comentario a la respuesta de Shuvalov). Solo diría, "estas cosas son solo para ASCII", pero es el operador "~~" el que funciona, así que no es como si el código y las tablas de traducción no estuvieran allí ...
Hubert Kario
44
@HubertKario: El responsable de mantenimiento de Bash ha reconocido el error y ha declarado que se solucionará en la próxima versión.
Pausado hasta nuevo aviso.
123
echo "Hi All" | tr "[:upper:]" "[:lower:]"
shuvalov
fuente
44
@RichardHansen: trno funciona para mí para personajes que no son ACII. Tengo el conjunto de configuración regional correcto y los archivos de configuración regional generados. ¿Tienes alguna idea de qué podría estar haciendo mal?
Hubert Kario
FYI: Esto funcionó en Windows / Msys. Algunas de las otras sugerencias no lo hicieron.
wasatchwizard
3
¿Por qué es [:upper:]necesario?
mgutt
77

tr :

a="$(tr [A-Z] [a-z] <<< "$a")"

AWK :

{ print tolower($0) }

sed :

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
Ignacio Vazquez-Abrams
fuente
2
+1 me a="$(tr [A-Z] [a-z] <<< "$a")"parece más fácil. Todavía soy un principiante ...
Sandeepan Nath
2
Recomiendo encarecidamente la sedsolución; He estado trabajando en un entorno que por alguna razón no tiene, trpero todavía tengo que encontrar un sistema sin él sed, y muchas veces quiero hacer esto. De sedtodos modos, he hecho algo más para encadenar los comandos juntos en una sola declaración (larga).
Haravikk
2
Las expresiones de paréntesis deben ser citadas. En tr [A-Z] [a-z] A, el shell puede realizar la expansión del nombre de archivo si hay nombres de archivo que consisten en una sola letra o se establece nullgob . tr "[A-Z]" "[a-z]" ASe comportará correctamente.
Dennis
2
@CamiloMartin es un sistema BusyBox donde tengo ese problema, específicamente Synology NAS, pero también lo he encontrado en algunos otros sistemas. Últimamente he estado haciendo muchas secuencias de comandos de shell multiplataforma, y ​​con el requisito de que no se instale nada adicional, ¡hace las cosas muy difíciles! Sin embargo, todavía no he encontrado un sistema sinsed
Haravikk
2
Tenga en cuenta que tr [A-Z] [a-z]es incorrecto en casi todas las configuraciones regionales. por ejemplo, en la en-USconfiguración regional, A-Zes en realidad el intervalo AaBbCcDdEeFfGgHh...XxYyZ.
fuz
44

Sé que esta es una publicación antigua pero hice esta respuesta para otro sitio, así que pensé en publicarla aquí:

SUPERIOR -> inferior : use python:

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

O rubí:

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

O Perl (probablemente mi favorito):

b=`perl -e "print lc('$a');"`

O PHP:

b=`php -r "print strtolower('$a');"`

O Awk:

b=`echo "$a" | awk '{ print tolower($1) }'`

O sed:

b=`echo "$a" | sed 's/./\L&/g'`

O Bash 4:

b=${a,,}

O NodeJS si lo tiene (y está un poco loco ...):

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

También podría usar dd(¡pero yo no lo haría!):

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

inferior -> SUPERIOR :

usar python:

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

O rubí:

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

O Perl (probablemente mi favorito):

b=`perl -e "print uc('$a');"`

O PHP:

b=`php -r "print strtoupper('$a');"`

O Awk:

b=`echo "$a" | awk '{ print toupper($1) }'`

O sed:

b=`echo "$a" | sed 's/./\U&/g'`

O Bash 4:

b=${a^^}

O NodeJS si lo tiene (y está un poco loco ...):

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

También podría usar dd(¡pero yo no lo haría!):

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

Además, cuando dices 'shell', supongo que quieres decir, bashpero si puedes usarlo zshes tan fácil como

b=$a:l

para minúsculas y

b=$a:u

para mayúsculas

nettux
fuente
@JESii ambos funcionan para mí upper -> lower y lower-> upper. Estoy usando sed 4.2.2 y Bash 4.3.42 (1) en Debian Stretch de 64 bits.
nettux
1
Hola, @ nettux443 ... Acabo de intentar la operación bash nuevamente y todavía me falla con el mensaje de error "mala sustitución". Estoy en OSX usando homebrew's bash: GNU bash, versión 4.3.42 (1) -release (x86_64-apple-darwin14.5.0)
JESii
55
¡No utilice! Todos los ejemplos que generan un script son extremadamente frágiles; Si el valor de acontiene una comilla simple, no solo tiene un comportamiento roto, sino un problema de seguridad grave.
tripleee
La solución sed me gusta más, ya que sed siempre es omnipresente.
Dudi Boy
Prefiero usar la solución dd. Tenga en cuenta que debe ser root para que funcione
inetphantom
29

En zsh:

echo $a:u

Tengo que amar zsh!

Scott Smedley
fuente
44
o $ a: l para la conversión de minúsculas
Scott Smedley
1
Agregue un caso más:echo ${(C)a} #Upcase the first char only
biocyberman
18

Usando GNU sed:

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

Ejemplo:

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

Pre Bash 4.0

Bash Baje el caso de una cadena y asigne a variable

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

echo "$VARIABLE"
hawkeye126
fuente
55
No hay necesidad echoy tuberías: uso$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Tino
3
@Tino La cadena here tampoco es portátil de vuelta a versiones realmente antiguas de Bash; Creo que se introdujo en v3.
tripleee
1
@tripleee Tienes razón, se introdujo en bash-2.05b; sin embargo, esa es la bash más antigua que pude encontrar en mis sistemas
Tino el
11

Para un caparazón estándar (sin bashisms) usando solo 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}"
}

Y para mayú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}"
}
technosaurus
fuente
Me pregunto si no permitiste un poco de bashism en este script, ya que no es portátil en FreeBSD sh: $ {1: $ ...}: Mala sustitución
Dereckson
2
En efecto; Las subcadenas con ${var:1:1}son un Bashismo.
tripleee
Este enfoque tiene métricas de rendimiento bastante malas. Vea mi respuesta para métricas.
Dejay Clayton
9

En bash 4 puedes usar la composición tipográfica

Ejemplo:

A="HELLO WORLD"
typeset -l A=$A
c4f4t0r
fuente
7

Expresión regular

Me gustaría tomar el crédito por el comando que deseo compartir, pero la verdad es que lo obtuve para mi propio uso en http://commandlinefu.com . Tiene la ventaja de que si cdutiliza un directorio dentro de su propia carpeta de inicio, cambiará todos los archivos y carpetas a minúsculas de forma recursiva, por favor, use con precaución. Es una solución de línea de comando brillante y especialmente útil para esas multitudes de álbumes que ha almacenado en su unidad.

find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

Puede especificar un directorio en lugar del punto (.) Después de la búsqueda que denota el directorio actual o la ruta completa.

Espero que esta solución sea útil, lo único que este comando no hace es reemplazar espacios con guiones bajos, bueno, quizás en otro momento.

Derek Shaw
fuente
Esto no funcionó para mí por cualquier razón, aunque se ve bien. Sin embargo, conseguí que esto funcionara como alternativa: find. -exec / bin / bash -c 'mv {} `tr [AZ] [az] <<< {}`' \;
John Rix
Esto necesita prenamede perl: dpkg -S "$(readlink -e /usr/bin/rename)"daperl: /usr/bin/prename
Tino
4

Muchas respuestas usando programas externos, que realmente no está usando Bash.

Si sabe que tendrá Bash4 disponible, realmente debería usar la ${VAR,,}notación (es fácil y genial). Para Bash antes de 4 (Mi Mac todavía usa Bash 3.2 por ejemplo). Usé la versión corregida de la respuesta de @ ghostdog74 para crear una versión más portátil.

Uno puede llamar lowercase 'my STRING'y obtener una versión en minúsculas. Leí comentarios sobre cómo establecer el resultado en un var, pero eso no es realmente portátil Bash, ya que no podemos devolver cadenas. Imprimirlo es la mejor solución. Fácil de capturar con algo así var="$(lowercase $str)".

Como funciona esto

La forma en que esto funciona es obteniendo la representación entera ASCII de cada carácter con printfy luego adding 32si upper-to->lower, o subtracting 32si lower-to->upper. Luego, use printfnuevamente para convertir el número de nuevo a un carácter. De 'A' -to-> 'a'tenemos una diferencia de 32 caracteres.

Usando printfpara explicar:

$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65

97 - 65 = 32

Y esta es la versión de trabajo con ejemplos.
Tenga en cuenta los comentarios en el código, ya que explican muchas cosas:

#!/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

Y los resultados después de ejecutar esto:

$ ./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!

Sin embargo, esto solo debería funcionar para los caracteres ASCII .

Para mí está bien, ya que sé que solo le pasaré caracteres ASCII.
Estoy usando esto para algunas opciones de CLI sin distinción entre mayúsculas y minúsculas, por ejemplo.

Gus Neves
fuente
4

La conversión de mayúsculas y minúsculas se realiza solo para alfabetos. Entonces, esto debería funcionar perfectamente.

Me estoy centrando en convertir alfabetos entre az de mayúsculas a minúsculas. Cualquier otro carácter debe imprimirse en stdout tal como está ...

Convierte todo el texto en la ruta / a / archivo / nombre de archivo dentro del rango az a AZ

Para convertir minúsculas a mayúsculas

cat path/to/file/filename | tr 'a-z' 'A-Z'

Para convertir de mayúsculas a minúsculas

cat path/to/file/filename | tr 'A-Z' 'a-z'

Por ejemplo,

nombre del archivo:

my name is xyz

se convierte a:

MY NAME IS XYZ

Ejemplo 2

echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK

Ejemplo 3

echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
theBuzzyCoder
fuente
3

Si usa v4, esto está horneado . Si no, aquí hay una solución simple y ampliamente aplicable . Otras respuestas (y comentarios) en este hilo fueron bastante útiles para crear el siguiente código.

# 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:

  • Hacer: a="Hi All"y luego: lcase ahará lo mismo que:a=$( echolcase "Hi All" )
  • En la función lcase, usar en ${!1//\'/"'\''"}lugar de ${!1}permite que esto funcione incluso cuando la cadena tiene comillas.
Stephen M. Harris
fuente
3

Para las versiones de Bash anteriores a la 4.0, esta versión debería ser la más rápida (ya que no bifurca / ejecuta ningún 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"
}

La respuesta del technosaurus también tenía potencial, aunque funcionó correctamente para mí.

Orwellophile
fuente
¡No está mal! Para un análisis del rendimiento de este enfoque, consulte mi respuesta para las métricas.
Dejay Clayton
3

A pesar de la antigüedad de esta pregunta y similar a la respuesta del technosaurus . Me costó encontrar una solución que fuera portátil en la mayoría de las plataformas (That I Use), así como en versiones anteriores de bash. También me he sentido frustrado con las matrices, las funciones y el uso de impresiones, ecos y archivos temporales para recuperar variables triviales. Esto funciona muy bien para mí hasta ahora, pensé que compartiría. Mis principales entornos de prueba son:

  1. GNU bash, versión 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
  2. GNU bash, versión 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 simple para que el bucle itere a través de las cadenas. Para la línea de abajo si no has visto algo así antes, aquí es donde aprendí esto . En este caso, la línea verifica si el char $ {input: $ i: 1} (minúscula) existe en la entrada y, de ser así, lo reemplaza con el char $ {ucs: $ j: 1} (mayúscula) dado y lo almacena de nuevo en la entrada.

input="${input/${input:$i:1}/${ucs:$j:1}}"
JaredTS486
fuente
Esto es muy ineficiente, se repite 650 veces en su ejemplo anterior y tarda 35 segundos en ejecutar 1000 invocaciones en mi máquina. Para una alternativa que se repite solo 11 veces y toma menos de 5 segundos para ejecutar 1000 invocaciones, vea mi respuesta alternativa.
Dejay Clayton
1
Gracias, aunque eso debería ser obvio con solo mirarlo. Quizás las fallas de la página provienen del tamaño de entrada y del número de iteraciones que está ejecutando. Sin embargo, me gusta tu solución.
JaredTS486
3

Esta es una variación mucho más rápida del enfoque de JaredTS486 que utiliza capacidades nativas de Bash (incluidas las versiones de Bash <4.0) para optimizar su enfoque.

He cronometrado 1,000 iteraciones de este enfoque para una cadena pequeña (25 caracteres) y una cadena más grande (445 caracteres), tanto para conversiones en minúsculas como en mayúsculas. Dado que las cadenas de prueba son predominantemente minúsculas, las conversiones a minúsculas son generalmente más rápidas que a mayúsculas.

Comparé mi enfoque con varias otras respuestas en esta página que son compatibles con Bash 3.2. Mi enfoque es mucho más eficaz que la mayoría de los enfoques documentados aquí, y es incluso más rápido que tren varios casos.

Estos son los resultados de tiempo para 1,000 iteraciones de 25 caracteres:

Resultados de tiempo para 1,000 iteraciones de 445 caracteres (que consiste en el poema "The Robin" de Witter Bynner):

  • 2s para mi enfoque de minúsculas; 12s para mayúsculas
  • 4s para trminúsculas; 4s para mayúsculas
  • 20 años para el enfoque de Orwellophile en minúsculas; 29s para mayúsculas
  • 75 para el enfoque de ghostdog74 en minúsculas; 669 para mayúsculas. Es interesante observar cuán dramática es la diferencia de rendimiento entre una prueba con coincidencias predominantes y una prueba con fallas predominantes
  • 467 para el enfoque del tecnosaurus en minúsculas; 449s para mayúsculas
  • 660 para el enfoque de JaredTS486 a minúsculas; 660 para mayúsculas. Es interesante notar que este enfoque generó fallas continuas en la página (intercambio de memoria) en Bash

Solución:

#!/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}"
}

El enfoque es simple: mientras que la cadena de entrada tiene presentes las letras mayúsculas restantes, encuentre la siguiente y reemplace todas las instancias de esa letra con su variante en minúsculas. Repita hasta que se reemplacen todas las letras mayúsculas.

Algunas características de rendimiento de mi solución:

  1. Utiliza solo utilidades integradas de shell, lo que evita la sobrecarga de invocar utilidades binarias externas en un nuevo proceso
  2. Evita subcapas, que incurren en penalizaciones de rendimiento
  3. Utiliza mecanismos de shell que se compilan y optimizan para el rendimiento, como el reemplazo global de cadenas dentro de las variables, el recorte de sufijos variables y la búsqueda y coincidencia de expresiones regulares. Estos mecanismos son mucho más rápidos que iterar manualmente a través de cadenas
  4. Repite solo el número de veces que requiere el recuento de caracteres coincidentes únicos para convertir. Por ejemplo, convertir una cadena que tiene tres caracteres en mayúsculas diferentes en minúsculas requiere solo 3 iteraciones de bucle. Para el alfabeto ASCII preconfigurado, el número máximo de iteraciones de bucle es 26
  5. UCSy LCSse puede aumentar con caracteres adicionales
Dejay Clayton
fuente
2

Para almacenar la cadena transformada en una variable. Siguiente funcionó para mí - $SOURCE_NAMEpara$TARGET_NAME

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

Manera simple

echo "Hi all" | awk '{ print tolower($0); }'
Atul23
fuente