Existe-t-il un moyen dans bash de convertir une chaîne en chaîne en minuscule?
Par exemple, si j'ai:
a="Hi all"
Je veux le convertir en:
"hi all"
Les sont de différentes manières:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
Vous pouvez rencontrer des problèmes de portabilité avec les exemples suivants:
$ 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
Dans Bash 4:
En minuscule
$ 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
À majuscule
$ 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
Basculer (non documenté, mais éventuellement configurable à la 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
Capitaliser (non documenté, mais éventuellement configurable à la compilation)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Titre case:
$ 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
Pour désactiver un attribut declare
, utilisez +
. Par exemple, declare +c string
. Cela affecte les affectations suivantes et non la valeur actuelle.
Les options declare
changent l'attribut de la variable, mais pas le contenu. Les réaffectations de mes exemples mettent à jour le contenu pour afficher les modifications.
Modifier:
Ajout de "bascule le premier caractère par Word" (${var~}
) comme suggéré par ghostdog74 .
Edit: Correction du comportement du tilde pour correspondre à Bash 4.3.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
Je sais que c’est un article ancien, mais j’ai fait cette réponse pour un autre site, alors j’ai pensé le poster ici:
UPPER -> lower : Utilisez python:
b=`echo "print '$a'.lower()" | python`
Ou Ruby:
b=`echo "print '$a'.downcase" | Ruby`
Ou Perl (probablement mon préféré):
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 si vous l'avez (et êtes un peu cinglé ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Vous pouvez aussi utiliser dd
(mais pas moi!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
inférieur -> UPPER :
utilisez python:
b=`echo "print '$a'.upper()" | python`
Ou Ruby:
b=`echo "print '$a'.upcase" | Ruby`
Ou Perl (probablement mon préféré):
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 si vous l'avez (et êtes un peu cinglé ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Vous pouvez aussi utiliser dd
(mais pas moi!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Aussi, quand vous dites 'Shell', je suppose que vous voulez dire bash
mais si vous pouvez utiliser zsh
c'est aussi simple que
b=$a:l
pour les minuscules et
b=$a:u
pour les majuscules.
En zsh:
echo $a:u
Je dois aimer zsh!
Utilisation de GNU sed
:
sed 's/.*/\L&/'
Exemple:
$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed 's/.*/\L&/')
$ echo "$foo"
some string
Pour un shell standard (sans bashismes) utilisant uniquement les fonctions intégrées:
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}"
}
Et pour les majuscules:
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}"
}
Pre Bash 4.0
Bash Diminue la casse d'une chaîne et affecte une variable
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
Dans bash 4, vous pouvez utiliser la composition
Exemple:
A="HELLO WORLD"
typeset -l A=$A
J'aimerais prendre le crédit de la commande que je souhaite partager, mais la vérité est que je l’ai obtenue pour mon usage personnel à partir de http://commandlinefu.com . Il a l'avantage que si vous cd
dans n'importe quel répertoire de votre propre dossier de base, tous les fichiers et dossiers en minuscules seront modifiés de manière récursive, veuillez utiliser ce paramètre avec prudence. C’est un correctif de ligne de commande brillant et particulièrement utile pour les multitudes d’albums que vous avez stockés sur votre lecteur.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Vous pouvez spécifier un répertoire à la place du point (.) Après la recherche, qui désigne le répertoire en cours ou le chemin complet.
J'espère que cette solution s'avère utile, mais cette commande ne permet pas de remplacer les espaces par des traits de soulignement - peut-être une autre fois.
Tu peux essayer ça
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/
En dépit de l'âge de cette question et semblable à cette réponse de technosaurus . J'ai eu du mal à trouver une solution portable sur la plupart des plateformes (That I Use) ainsi que sur les anciennes versions de bash. J'ai également été frustré par les tableaux, les fonctions et l'utilisation des impressions, des échos et des fichiers temporaires pour récupérer des variables triviales. Cela fonctionne très bien pour moi jusqu'à présent, je pensais partager . Mes principaux environnements de test sont:
- GNU bash, version 4.1.2 (1) - release (x86_64-redhat-linux-gnu)
- GNU bash, version 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
Simple C-style for loop pour parcourir les chaînes . Pour la ligne ci-dessous si vous n'avez jamais rien vu de tel auparavant c'est ici que j'ai appris cela . Dans ce cas, la ligne vérifie si le caractère $ {input: $ i: 1} (minuscule) existe en entrée et, le cas échéant, le remplace par le caractère donné $ {ucs: $ j: 1} (majuscule) et le stocke. retour en entrée.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Pour les versions de Bash antérieures à 4.0, cette version devrait être la plus rapide (car elle ne prend pas fork/exec aucune commande):
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 réponse de technosaurus avait aussi du potentiel, même si elle a fonctionné correctement pour moi.
Si vous utilisez v4, c’est cuit au four . Sinon, voici une solution simple, largement applicable. D'autres réponses (et commentaires) sur ce fil ont été très utiles pour créer le code ci-dessous.
# 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:] )\'
}
Notes:
a="Hi All"
et ensuite: lcase a
fera la même chose que: a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
au lieu de ${!1}
permet que cela fonctionne même lorsque la chaîne contient des guillemets.Beaucoup de réponses utilisent des programmes externes, qui n'utilisent pas vraiment Bash
.
Si vous savez que vous aurez Bash4 disponible, vous devriez vraiment utiliser la notation ${VAR,,}
(c’est facile et cool). Pour Bash avant 4 (Mon Mac utilise toujours Bash 3.2 par exemple). J'ai utilisé la version corrigée de la réponse de @ ghostdog74 pour créer une version plus portable.
Celui que vous pouvez appeler lowercase 'my STRING'
et obtenir une version minuscule. J'ai lu des commentaires sur la définition du résultat dans une variable, mais ce n'est pas vraiment portable dans Bash
, car nous ne pouvons pas renvoyer de chaînes. L'imprimer est la meilleure solution. Facile à capturer avec quelque chose comme var="$(lowercase $str)"
.
Comment ça marche
Cela fonctionne en obtenant la représentation ASCII entière de chaque caractère avec printf
, puis adding 32
si upper-to->lower
ou subtracting 32
si lower-to->upper
. Utilisez ensuite à nouveau printf
pour reconvertir le nombre en caractère. De 'A' -to-> 'a'
nous avons une différence de 32 caractères.
Utiliser printf
pour expliquer:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
Et ceci est la version de travail avec des exemples.
Veuillez noter les commentaires dans le code, car ils expliquent beaucoup de choses:
#!/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
Et les résultats après avoir exécuté ceci:
$ ./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!
Ceci ne devrait fonctionner que pour les caractères ASCII bien que .
Pour moi, ça va, puisque je sais que je ne lui transmettrai que des caractères ASCII.
J'utilise ceci pour certaines options CLI qui respectent la casse, par exemple.
Si vous aimez python et avez la possibilité d'installer un nouveau package python, vous pouvez essayer cet utilitaire python .
# install pythonp
$ pip install pythonp
$ echo $a | pythonp "l.lower()"
La conversion de casse est effectuée uniquement pour les alphabets. Donc, cela devrait fonctionner proprement.
Je me concentre sur la conversion des alphabets entre a-z de majuscules à minuscules. Tous les autres caractères doivent simplement être imprimés dans stdout tels quels.
Convertit tout le texte dans path/to/file/filename dans la plage a-z en A-Z
Pour convertir les minuscules en majuscules
cat path/to/file/filename | tr 'a-z' 'A-Z'
Pour convertir des majuscules en minuscules
cat path/to/file/filename | tr 'A-Z' 'a-z'
Par exemple,
nom de fichier:
my name is xyz
se convertit en:
MY NAME IS XYZ
Exemple 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Exemple 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Pour stocker la chaîne transformée dans une variable. Suivre a travaillé pour moi -$SOURCE_NAME
à $TARGET_NAME
TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"
Il s’agit d’une variante beaucoup plus rapide de l’approche de JaredTS486 qui utilise les fonctionnalités natives de Bash (y compris les versions de Bash <4.0) pour optimiser son approche.
J'ai chronométré 1 000 itérations de cette approche pour une petite chaîne (25 caractères) et une plus grande chaîne (445 caractères), pour les conversions minuscules et majuscules. Étant donné que les chaînes de test sont principalement en minuscules, les conversions en minuscules sont généralement plus rapides qu'en majuscules.
J'ai comparé mon approche avec plusieurs autres réponses sur cette page, compatibles avec Bash 3.2. Mon approche est beaucoup plus performante que la plupart des approches décrites ici et est même plus rapide que tr
dans plusieurs cas.
Voici les résultats de minutage pour 1000 itérations de 25 caractères:
tr
à minuscule; 3.81s pour les majusculesRésultats chronométrés pour 1 000 itérations de 445 caractères (comprenant le poème "The Robin" de Witter Bynner):
tr
à minuscule; 4s pour les majusculesSolution:
#!/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}"
}
L’approche est simple: même s’il reste des lettres majuscules dans la chaîne d’entrée, recherchez la suivante et remplacez toutes les occurrences de cette lettre par sa variante minuscule. Répétez l'opération jusqu'à ce que toutes les lettres majuscules soient remplacées.
Quelques caractéristiques de performance de ma solution:
UCS
et LCS
peuvent être complétés par des caractères supplémentaires