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.
tr
y awk
se 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 declare
atributo, use +
. Por ejemplo, declare +c string
. Esto afecta las asignaciones posteriores y no el valor actual.
Las declare
opciones 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:]"
tr
no 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 ...
sed
solución; He estado trabajando en un entorno que por alguna razón no tiene, tr
pero todavía tengo que encontrar un sistema sin él sed
, y muchas veces quiero hacer esto. De sed
todos 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]" A
Se comportará correctamente.
sed
tr [A-Z] [a-z]
es incorrecto en casi todas las configuraciones regionales. por ejemplo, en la en-US
configuración regional, A-Z
es 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, bash
pero si puedes usarlo zsh
es tan fácil como
b=$a:l
para minúsculas y
b=$a:u
para mayúsculas
a
contiene 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"
echo
y 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 cd
utiliza 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.
prename
de 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 printf
y luego adding 32
si upper-to->lower
, o subtracting 32
si lower-to->upper
. Luego, use printf
nuevamente para convertir el número de nuevo a un carácter. De 'A' -to-> 'a'
tenemos una diferencia de 32 caracteres.
Usando printf
para 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 a
hará 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 tr
en varios casos.
Estos son los resultados de tiempo para 1,000 iteraciones de 25 caracteres:
tr
minú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):
tr
minú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:
UCS
y LCS
se puede aumentar con caracteres adicionales