Respuestas:
Hay varias formas:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
Puede encontrar problemas de portabilidad con los siguientes ejemplos:
$ 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 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")! :-)
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.
try awkse especifican en el estándar POSIX.
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.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
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.
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.
en_US.UTF-8. Es un error y lo he informado.
echo "$string" | tr '[:lower:]' '[:upper:]'. Probablemente exhibirá la misma falla. Entonces, el problema no es al menos en parte de Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
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?
[:upper:]necesario?
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"parece más fácil. Todavía soy un principiante ...
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).
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.
sed
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.
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
acontiene una comilla simple, no solo tiene un comportamiento roto, sino un problema de seguridad grave.
En zsh:
echo $a:u
Tengo que amar zsh!
echo ${(C)a} #Upcase the first char only
Pre Bash 4.0
Bash Baje el caso de una cadena y asigne a variable
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echoy tuberías: uso$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
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}"
}
${var:1:1}son un Bashismo.
Puedes probar esto
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/
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.
prenamede perl: dpkg -S "$(readlink -e /usr/bin/rename)"daperl: /usr/bin/prename
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.
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
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:
a="Hi All"y luego: lcase ahará lo mismo que:a=$( echolcase "Hi All" )${!1//\'/"'\''"}lugar de ${!1}permite que esto funcione incluso cuando la cadena tiene comillas.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í.
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:
- GNU bash, versión 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
- 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}}"
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:
trminúsculas; 3.81s para mayúsculasResultados de tiempo para 1,000 iteraciones de 445 caracteres (que consiste en el poema "The Robin" de Witter Bynner):
trminúsculas; 4s para mayúsculasSolució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:
UCSy LCSse puede aumentar con caracteres adicionales