Réponses:
Il existe 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
Remarque: YMMV sur celui-ci. Ne fonctionne pas pour moi (GNU bash version 4.2.46 et 4.0.33 (et même comportement 2.05b.0 mais nocasematch n'est pas implémenté)) même avec using shopt -u nocasematch;
. Ne pas définir que nocasematch fait que [["fooBaR" == "FOObar"]] correspond à OK MAIS étrangement à l'intérieur de la casse [bz] est incorrectement mis en correspondance par [AZ]. Bash est confondu par le double négatif ("unsetting nocasematch")! :-)
word="Hi All"
comme les autres exemples, il revient ha
, non hi all
. Il ne fonctionne que pour les lettres majuscules et ignore les lettres déjà en minuscules.
tr
et awk
sont spécifiés dans la norme POSIX.
tr '[:upper:]' '[:lower:]'
utilisera les paramètres régionaux actuels pour déterminer les équivalents majuscules / minuscules, donc cela fonctionnera avec les paramètres régionaux qui utilisent des lettres avec des signes diacritiques.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
Dans Bash 4:
Pour 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
En majuscules
$ 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 (non documenté, mais configurable en option au moment de 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 configurable en option au moment de la compilation)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Cas de titre:
$ 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 declare
attribut, utilisez +
. Par exemple declare +c string
,. Cela affecte les affectations suivantes et non la valeur actuelle.
Les declare
options modifient l'attribut de la variable, mais pas le contenu. Les réaffectations dans mes exemples mettent à jour le contenu pour montrer les changements.
Éditer:
Ajout de "basculer le premier caractère par mot" ( ${var~}
) comme suggéré par ghostdog74 .
Edit: comportement tilde corrigé pour correspondre à Bash 4.3.
string="łódź"; echo ${string~~}
, retournera "ŁÓDŹ", mais echo ${string^^}
renverra "łóDź". Même en LC_ALL=pl_PL.utf-8
. Cela utilise bash 4.2.24.
en_US.UTF-8
. C'est un bug et je l'ai signalé.
echo "$string" | tr '[:lower:]' '[:upper:]'
. Il présentera probablement le même échec. Le problème n'est donc pas au moins en partie celui de Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr
ne fonctionne pas pour moi pour les personnages non-ACII. J'ai un ensemble de paramètres régionaux correct et des fichiers de paramètres régionaux générés. Avez-vous une idée de ce que je pourrais faire de mal?
[:upper:]
nécessaire?
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"
me semble le plus simple. Je suis toujours un débutant ...
sed
solution; J'ai travaillé dans un environnement qui, pour une raison quelconque, n'en a pas, tr
mais je n'ai pas encore trouvé de système sans sed
, et la plupart du temps je veux le faire, je viens de faire quelque chose d'autre de sed
toute façon, donc je peux enchaîner les commandes ensemble dans une seule instruction (longue).
tr [A-Z] [a-z] A
, le shell peut effectuer une expansion du nom de fichier s'il existe des noms de fichiers composés d'une seule lettre ou si nullgob est défini. tr "[A-Z]" "[a-z]" A
se comportera correctement.
sed
tr [A-Z] [a-z]
c'est incorrect dans presque tous les environnements locaux. par exemple, dans les en-US
paramètres régionaux, A-Z
est en fait l'intervalle AaBbCcDdEeFfGgHh...XxYyZ
.
Je sais que c'est un article ancien mais j'ai fait cette réponse pour un autre site, alors j'ai pensé le publier 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 fou ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Vous pouvez également utiliser dd
(mais je ne le ferais pas!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
inférieur -> SUPÉRIEUR :
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 fou ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Vous pouvez également utiliser dd
(mais je ne le ferais pas!):
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 l'utiliser, zsh
c'est aussi simple que
b=$a:l
pour les minuscules et
b=$a:u
pour les majuscules.
a
contient une seule citation, vous avez non seulement un comportement défectueux, mais un grave problème de sécurité.
En zsh:
echo $a:u
Je dois aimer zsh!
echo ${(C)a} #Upcase the first char only
Pre Bash 4.0
Bash Abaissez la casse d'une chaîne et affectez-la à une variable
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echo
tuyaux: utilisez$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Pour un shell standard (sans bashismes) utilisant uniquement des 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}"
}
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}"
}
${var:1:1}
sont un bashisme.
Vous pouvez essayer ceci
s="Hello World!"
echo $s # Hello World!
a=${s,,}
echo $a # hello world!
b=${s^^}
echo $b # HELLO WORLD!
réf: http://wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/
Je voudrais prendre le crédit de la commande que je souhaite partager, mais la vérité est que je l'ai obtenue pour mon propre usage sur http://commandlinefu.com . Il a l'avantage que si vous accédez cd
à n'importe quel répertoire de votre propre dossier de départ, cela changera tous les fichiers et dossiers en minuscules de manière récursive, veuillez les utiliser avec prudence. C'est une solution brillante en ligne de commande et particulièrement utile pour les multitudes d'albums que vous avez stockés sur votre disque.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Vous pouvez spécifier un répertoire à la place du point (.) Après la recherche qui indique le répertoire actuel ou le chemin complet.
J'espère que cette solution s'avère utile la seule chose que cette commande ne fait pas est de remplacer les espaces par des traits de soulignement - eh bien une autre fois peut-être.
prename
de perl
: dpkg -S "$(readlink -e /usr/bin/rename)"
donneperl: /usr/bin/prename
Beaucoup de réponses en utilisant des programmes externes, ce qui n'est pas vraiment utile Bash
.
Si vous savez que Bash4 sera disponible, vous devriez vraiment utiliser la ${VAR,,}
notation (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 en minuscules. J'ai lu des commentaires sur la définition du résultat sur une variable, mais ce n'est pas vraiment portable Bash
, car nous ne pouvons pas retourner de chaînes. L'imprimer est la meilleure solution. Facile à capturer avec quelque chose comme var="$(lowercase $str)"
.
Comment ça marche
La façon dont cela fonctionne consiste à obtenir la représentation entière ASCII de chaque caractère avec printf
puis adding 32
si upper-to->lower
, ou subtracting 32
si lower-to->upper
. Ensuite, utilisez à printf
nouveau 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!
Cela ne devrait cependant fonctionner que pour les caractères ASCII .
Pour moi, c'est bien, car je sais que je ne lui transmettrai que des caractères ASCII.
Je l'utilise pour certaines options CLI insensibles à la casse, par exemple.
La conversion de la casse est effectuée uniquement pour les alphabets. Donc, cela devrait fonctionner parfaitement.
Je me concentre sur la conversion des alphabets entre az de majuscules en minuscules. Tout autre caractère doit simplement être imprimé dans stdout tel quel ...
Convertit tout le texte du chemin / vers / fichier / nom de fichier dans la plage az en AZ
Pour convertir des minuscules en majuscules
cat path/to/file/filename | tr 'a-z' 'A-Z'
Pour la conversion de majuscules en minuscules
cat path/to/file/filename | tr 'A-Z' 'a-z'
Par exemple,
nom de fichier:
my name is xyz
est converti 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
Si vous utilisez v4, cela est intégré . Sinon, voici une solution simple et 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:] )\'
}
Remarques:
a="Hi All"
et ensuite: lcase a
fera la même chose que:a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
au lieu de ${!1}
permet à cela de fonctionner même lorsque la chaîne a des guillemets.Pour les versions de Bash antérieures à 4.0, cette version devrait être la plus rapide (car elle ne fork / n'exécute 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 fonctionnait correctement pour moi.
Malgré l'âge de cette question et similaire à cette réponse du technosaurus . J'ai eu du mal à trouver une solution portable sur la plupart des plates-formes (que j'utilise) 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 que je partagerais. 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
Style C simple pour une boucle pour parcourir les cordes. Pour la ligne ci-dessous, si vous n'avez jamais rien vu de tel auparavant, c'est là 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 si c'est le cas le remplace par le caractère donné $ {ucs: $ j: 1} (majuscule) et le stocke en entrée.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Il s'agit d'une variante beaucoup plus rapide de l'approche de JaredTS486 qui utilise les capacités natives de Bash (y compris les versions Bash <4.0) pour optimiser son approche.
J'ai chronométré 1000 itérations de cette approche pour une petite chaîne (25 caractères) et une chaîne plus grande (445 caractères), à la fois pour les conversions en minuscules et en 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 qui sont compatibles avec Bash 3.2. Mon approche est beaucoup plus performante que la plupart des approches documentées ici, et est encore plus rapide que tr
dans plusieurs cas.
Voici les résultats de chronométrage pour 1000 itérations de 25 caractères:
tr
minuscule; 3.81s pour les majusculesRésultats de chronométrage pour 1000 itérations de 445 caractères (composé du poème "Le 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: alors que la chaîne d'entrée contient toutes les lettres majuscules restantes, recherchez la suivante et remplacez toutes les instances de cette lettre par sa variante minuscule. Répétez jusqu'à ce que toutes les lettres majuscules soient remplacées.
Quelques caractéristiques de performance de ma solution:
UCS
et LCS
peut être augmenté de caractères supplémentaires