string - programas - scripts bash ejemplos
¿Cómo convertir una cadena a minúsculas en Bash? (19)
Expresión regular
Me gustaría tomar 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
a cualquier directorio dentro de su propia carpeta de inicio cambiará todos los archivos y carpetas a minúsculas de forma recursiva, por favor use con cuidado. Es una solución brillante para la línea de comandos y especialmente útil para las multitudes de álbumes que ha almacenado en su disco.
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 no puede hacer este comando es reemplazar los espacios con guiones bajos, bueno, quizás en otra ocasión.
¿Hay alguna forma en bash para convertir una cadena en una cadena minúscula?
Por ejemplo, si tengo:
a="Hi all"
Quiero convertirlo a:
"hi all"
A pesar de la edad de esta pregunta y similar a esta respuesta por tecnosaurus . 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 los arreglos, 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 iba a compartir. 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
Sencillo estilo C para que el bucle recorra las cadenas. Para la línea de abajo, si no has visto nada como esto antes, aquí es donde aprendí esto . En este caso, la línea verifica si la entrada char $ {input: $ i: 1} (minúscula) existe en la entrada y, si es así, la reemplaza por la char char dada {ucs: $ j: 1} (mayúscula) y la almacena de nuevo en la entrada.
input="${input/${input:$i:1}/${ucs:$j:1}}"
El caso de conversión se hace para alfabetos solamente. Por lo tanto, esto debería funcionar perfectamente.
Me estoy enfocando en convertir alfabetos entre az de mayúsculas a minúsculas. Cualquier otro carácter debería imprimirse en la salida estándar tal como está ...
Convierte todo el texto en ruta / a / archivo / nombre de archivo dentro de un rango de 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
En Bash 4:
A 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
Alternar (sin documentar, pero configurable opcionalmente 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 (sin documentar, 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 atributo declare
, use +
. Por ejemplo, declare +c string
. Esto afecta las asignaciones posteriores y no el valor actual.
Las opciones de declare
cambian el atributo de la variable, pero no el contenido. Las reasignaciones en mis ejemplos actualizan los contenidos para mostrar los cambios.
Editar:
Se agregó "cambiar el primer carácter por palabra" ( ${var~}
) según lo sugerido por ghostdog74 .
Edición: se corrigió el comportamiento de tilde para que coincida con Bash 4.3.
En bash 4 puedes usar tipografía.
Ejemplo:
A="HELLO WORLD"
typeset -l A=$A
En zsh:
echo $a:u
Tengo que amar a zsh!
Esta es una variación mucho más rápida del enfoque de JaredTS486 que usa las 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 en minúsculas, las conversiones a minúsculas son generalmente más rápidas que en mayúsculas.
He comparado mi enfoque con 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.
Aquí están los resultados de tiempo para 1,000 iteraciones de 25 caracteres:
- 0.46s para mi acercamiento a minúsculas; 0.96s para mayúsculas
- 1.16s para el enfoque de Orwellophile a minúsculas; 1.59s para mayúsculas
- 3.67s para
tr
a minúsculas; 3.81s para mayúsculas - 11.12s para el enfoque de ghostdog74 a minúsculas; 31.41s para mayúsculas
- 26.25s para el acercamiento de technosaurus a minúsculas; 26.21s para mayúsculas
- 25.06s para el enfoque de JaredTS486 a minúsculas; 27.04s para mayúsculas
Resultados de tiempo para 1,000 iteraciones de 445 caracteres (consistente en el poema "The Robin" de Witter Bynner):
- 2s para mi acercamiento a minúsculas; 12s para mayúsculas
- 4s para
tr
a minúsculas; 4s para mayúsculas - 20 años para el enfoque de Orwellophile a minúsculas; 29s para mayúsculas
- 75s para el acercamiento de ghostdog74 a minúsculas; 669s 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
- 467s para el enfoque de technosaurus a minúsculas; 449s para mayúsculas
- 660s para el enfoque de JaredTS486 a minúsculas; 660s para mayúsculas. Es interesante observar que este enfoque generó fallas de página continuas (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 cualquier otra letra mayúscula presente, encuentre la siguiente y reemplace todas las instancias de esa letra con su variante en minúscula. Repita hasta que todas las letras mayúsculas sean reemplazadas.
Algunas características de rendimiento de mi solución:
- Utiliza solo utilidades incorporadas en el shell, lo que evita la sobrecarga de invocar utilidades binarias externas en un nuevo proceso
- Evita sub-shells, que incurren en penalizaciones de rendimiento.
- Utiliza mecanismos de shell compilados y optimizados 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 la iteración manual a través de cadenas
- Repite solo el número de veces requerido por el recuento de caracteres coincidentes únicos para convertir. Por ejemplo, convertir una cadena que tiene tres caracteres en mayúscula diferentes a minúsculas requiere solo 3 iteraciones de bucle. Para el alfabeto ASCII preconfigurado, el número máximo de iteraciones de bucle es 26
-
UCS
yLCS
se pueden aumentar con caracteres adicionales
Hay varias maneras:
Estándar POSIX
tr
$ echo "$a" | tr ''[:upper:]'' ''[:lower:]''
hi all
AWK
$ echo "$a" | awk ''{print tolower($0)}''
hi all
No posix
Puede tener 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
Muchas respuestas usando programas externos, que en realidad no usa Bash
.
Si sabes que tendrás Bash4 disponible, deberías usar la notación ${VAR,,}
(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 al que puedes llamar en lowercase ''my STRING''
y obtener una versión en minúscula. Leí los comentarios acerca de establecer el resultado en una var, pero eso no es realmente portátil en Bash
, ya que no podemos devolver cadenas. Imprimirlo es la mejor solución. Fácil de capturar con algo como 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 es upper-to->lower
, o subtracting 32
si es lower-to->upper
. A continuación, utilice printf
nuevo para convertir el número de nuevo a un carácter. Desde ''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é los caracteres ASCII.
Estoy usando esto para algunas opciones de CLI que no distinguen entre mayúsculas y minúsculas, por ejemplo.
Para almacenar la cadena transformada en una variable. Los siguientes me funcionaron: de $SOURCE_NAME
a $TARGET_NAME
TARGET_NAME="`echo $SOURCE_NAME | tr ''[:upper:]'' ''[:lower:]''`"
Para una cáscara estándar (sin bashismos) que usa 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}"
}
Para versiones de Bash anteriores a 4.0, esta versión debería ser más rápida (ya que no fork/exec 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 de Technosaurus también tenía potencial, aunque funcionó correctamente para mí.
Pre Bash 4.0
Bash baja el caso de una cadena y asigna a variable
VARIABLE=$(echo "$VARIABLE" | tr ''[:upper:]'' ''[:lower:]'')
echo "$VARIABLE"
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/
Sé que esta es una publicación antigua, pero hice esta respuesta para otro sitio, así que pensé que la publicaría aquí:
SUPERIOR -> inferior : usar python:
b=`echo "print ''$a''.lower()" | python`
O Ruby:
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 tienes (y estás un poco loco ...):
b=`echo "console.log(''$a''.toLowerCase());" | node`
También puedes usar dd
(¡pero yo no!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
inferior -> SUPERIOR :
utilizar python:
b=`echo "print ''$a''.upper()" | python`
O Ruby:
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 tienes (y estás un poco loco ...):
b=`echo "console.log(''$a''.toUpperCase());" | node`
También puedes usar dd
(¡pero yo no!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
También cuando dices ''shell'' supongo que te refieres a bash
pero si puedes usar zsh
es tan fácil como
b=$a:l
para minúsculas y
b=$a:u
para mayúsculas
Si usa v4, este es baked-in . Si no, aquí hay una solución simple y ampliamente aplicable . Otras respuestas (y comentarios) en este hilo fueron muy ú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:
- Haciendo:
a="Hi All"
y luego:lcase a
hará lo mismo que:a=$( echolcase "Hi All" )
- En la función lcase, usar
${!1///'/"''/'''"}
lugar de${!1}
permite que esto funcione incluso cuando la cadena tiene comillas.
Usando GNU sed
:
sed ''s/.*//L&/''
Ejemplo:
$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed ''s/.*//L&/'')
$ echo "$foo"
some string
echo "Hi All" | tr "[:upper:]" "[:lower:]"