Risposte:
Esistono vari modi:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
È possibile riscontrare problemi di portabilità con i seguenti esempi:
$ 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 su questo. Non funziona per me (GNU bash versione 4.2.46 e 4.0.33 (e lo stesso comportamento 2.05b.0 ma nocasematch non è implementato)) anche con l'utilizzo shopt -u nocasematch;
. Annullando l'impostazione di nocasematch, [["fooBaR" == "FOObar"]] corrisponde a OK MA all'interno del caso stranamente [bz] viene erroneamente identificato da [AZ]. Bash è confuso dal doppio negativo ("unsas nocasematch")! :-)
word="Hi All"
come gli altri esempi, ritorna ha
, no hi all
. Funziona solo con le lettere maiuscole e salta le lettere già minuscole.
tr
e awk
sono specificati nello standard POSIX.
tr '[:upper:]' '[:lower:]'
utilizzerà le impostazioni internazionali correnti per determinare gli equivalenti maiuscoli / minuscoli, quindi funzionerà con i locali che usano lettere con segni diacritici.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
In Bash 4:
In minuscolo
$ 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
Maiuscolo
$ 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
Attiva / disattiva (non documentato, ma facoltativamente configurabile in fase di compilazione)
$ 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
Capitalizzare (non documentato, ma facoltativamente configurabile in fase di compilazione)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Caso del titolo:
$ 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
Per disattivare un declare
attributo, utilizzare +
. Ad esempio declare +c string
,. Ciò influisce sulle assegnazioni successive e non sul valore corrente.
Le declare
opzioni cambiano l'attributo della variabile, ma non il contenuto. Le riassegnazioni nei miei esempi aggiornano i contenuti per mostrare le modifiche.
Modificare:
Aggiunto " attiva / disattiva il primo carattere per parola" ( ${var~}
) come suggerito da ghostdog74 .
Modifica: corretto comportamento della tilde per abbinare Bash 4.3.
string="łódź"; echo ${string~~}
restituirà "ŁÓDŹ", ma echo ${string^^}
restituisce "łóDź". Anche dentro LC_ALL=pl_PL.utf-8
. Sta usando bash 4.2.24.
en_US.UTF-8
. È un bug e l'ho segnalato.
echo "$string" | tr '[:lower:]' '[:upper:]'
. Probabilmente mostrerà lo stesso fallimento. Quindi il problema non è almeno in parte di Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr
non funziona per me per i personaggi non ACII. Ho un set di impostazioni internazionali corretto e file di localizzazione generati. Hai idea di cosa potrei fare di sbagliato?
[:upper:]
necessario
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"
mi sembra più semplice. Sono ancora un principiante ...
sed
soluzione; Ho lavorato in un ambiente che per qualche ragione non ha, tr
ma non ho ancora trovato un sistema senza sed
, e per la maggior parte del tempo che voglio farlo, ho appena fatto qualcos'altro in sed
modo da poter fare catena i comandi insieme in una singola (lunga) istruzione.
tr [A-Z] [a-z] A
, la shell può eseguire l'espansione del nome file se ci sono nomi di file costituiti da una sola lettera o è impostato nullgob . tr "[A-Z]" "[a-z]" A
si comporterà correttamente.
sed
tr [A-Z] [a-z]
non è corretto in quasi tutte le versioni locali. ad esempio, nella en-US
locale, A-Z
è in realtà l'intervallo AaBbCcDdEeFfGgHh...XxYyZ
.
So che questo è un post vecchio ma ho fatto questa risposta per un altro sito, quindi ho pensato di pubblicarlo qui:
UPPER -> lower : usa python:
b=`echo "print '$a'.lower()" | python`
O Ruby:
b=`echo "print '$a'.downcase" | ruby`
O Perl (probabilmente il mio preferito):
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 se ce l'hai (e sei un po 'fuori di testa ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Potresti anche usare dd
(ma io no!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
inferiore -> SUPERIORE :
usa python:
b=`echo "print '$a'.upper()" | python`
O Ruby:
b=`echo "print '$a'.upcase" | ruby`
O Perl (probabilmente il mio preferito):
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 se ce l'hai (e sei un po 'fuori di testa ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Potresti anche usare dd
(ma io no!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Anche quando dici "shell", suppongo che intendi, bash
ma se puoi usarlo zsh
è facile come
b=$a:l
per lettere minuscole e
b=$a:u
per maiuscole.
a
contiene una singola citazione, non hai solo un comportamento non corretto, ma un grave problema di sicurezza.
In zsh:
echo $a:u
Devi amare zsh!
echo ${(C)a} #Upcase the first char only
Pre Bash 4.0
Bash Abbassa il caso di una stringa e assegna a variabile
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echo
e tubi: utilizzare$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Per una shell standard (senza bashismi) usando solo builtin:
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}"
}
E per le maiuscole:
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}
sono un bashismo.
Puoi provare questo
s="Hello World!"
echo $s # Hello World!
a=${s,,}
echo $a # hello world!
b=${s^^}
echo $b # HELLO WORLD!
rif: http://wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/
Vorrei prendere il merito per il comando che desidero condividere, ma la verità è che l'ho ottenuto per uso personale da http://commandlinefu.com . Ha il vantaggio che se si cd
passa a qualsiasi directory all'interno della propria cartella home, cambierà tutti i file e le cartelle in minuscole ricorsivamente, si prega di usare con cautela. È una brillante correzione della riga di comando e particolarmente utile per quelle moltitudini di album che hai memorizzato sul tuo disco.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
È possibile specificare una directory al posto del punto (.) Dopo la ricerca che indica la directory corrente o il percorso completo.
Spero che questa soluzione si riveli utile, l'unica cosa che questo comando non fa è sostituire gli spazi con caratteri di sottolineatura - vabbè un'altra volta forse.
prename
di perl
: dpkg -S "$(readlink -e /usr/bin/rename)"
dàperl: /usr/bin/prename
Molte risposte utilizzano programmi esterni, che in realtà non stanno utilizzando Bash
.
Se sai che avrai Bash4 disponibile, dovresti semplicemente usare la ${VAR,,}
notazione (è facile e interessante). Per Bash prima dei 4 (il mio Mac usa ancora Bash 3.2 per esempio). Ho usato la versione corretta della risposta di @ ghostdog74 per creare una versione più portatile.
Uno che puoi chiamare lowercase 'my STRING'
e ottenere una versione minuscola. Ho letto i commenti sull'impostazione del risultato su un var, ma questo non è realmente portabile in Bash
quanto non possiamo restituire stringhe. La stampa è la soluzione migliore. Facile da catturare con qualcosa del genere var="$(lowercase $str)"
.
Come funziona
Il modo in cui funziona è ottenendo la rappresentazione intera ASCII di ciascun carattere con printf
e quindi adding 32
se upper-to->lower
, o subtracting 32
se lower-to->upper
. Quindi utilizzare printf
nuovamente per riconvertire il numero in un carattere. Da 'A' -to-> 'a'
abbiamo una differenza di 32 caratteri.
Usando printf
per spiegare:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
E questa è la versione funzionante con esempi.
Nota i commenti nel codice, poiché spiegano molte cose:
#!/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
E i risultati dopo aver eseguito questo:
$ ./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!
Questo dovrebbe funzionare solo per i caratteri ASCII .
Per me va bene, dato che so che gli passerò solo caratteri ASCII.
Lo sto usando per alcune opzioni della CLI senza distinzione tra maiuscole e minuscole, ad esempio.
La conversione del caso viene eseguita solo per alfabeti. Quindi, questo dovrebbe funzionare in modo ordinato.
Mi sto concentrando sulla conversione di alfabeti da az da maiuscolo a minuscolo. Tutti gli altri personaggi dovrebbero essere stampati in stdout così com'è ...
Converte tutto il testo nel percorso / in / file / nomefile nell'intervallo az in AZ
Per convertire lettere minuscole in maiuscole
cat path/to/file/filename | tr 'a-z' 'A-Z'
Per la conversione da lettere maiuscole a lettere minuscole
cat path/to/file/filename | tr 'A-Z' 'a-z'
Per esempio,
nome del file:
my name is xyz
viene convertito in:
MY NAME IS XYZ
Esempio 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Esempio 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Se si utilizza v4, questo è cotto . In caso contrario, ecco una soluzione semplice e ampiamente applicabile . Altre risposte (e commenti) su questo thread sono state molto utili nella creazione del codice seguente.
# 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:] )\'
}
Appunti:
a="Hi All"
e poi: lcase a
farà la stessa cosa di:a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
invece di ${!1}
consente a questo di funzionare anche quando la stringa ha virgolette.Per le versioni di Bash precedenti alla 4.0, questa versione dovrebbe essere la più veloce (poiché non esegue il fork / exec di alcun 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"
}
Anche la risposta di technosaurus aveva un potenziale, sebbene funzionasse correttamente per me.
Nonostante quanti anni questa domanda sia simile a questa risposta del technosaurus . Ho avuto difficoltà a trovare una soluzione portatile su gran parte delle piattaforme (That I Use) e versioni precedenti di bash. Sono stato anche frustrato dalle matrici, dalle funzioni e dall'uso di stampe, echi e file temporanei per recuperare variabili insignificanti. Questo funziona molto bene per me finora ho pensato di condividere. I miei principali ambienti di test sono:
- GNU bash, versione 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
- GNU bash, versione 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
Semplice stile C per il loop per scorrere le stringhe. Per la riga qui sotto se non hai visto nulla di simile prima di questo è dove ho imparato questo . In questo caso la riga controlla se il carattere $ {input: $ i: 1} (minuscolo) esiste nell'input e in tal caso lo sostituisce con il carattere $ $ {ucs: $ j: 1} (maiuscolo) e lo memorizza di nuovo in input.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Questa è una variante molto più veloce dell'approccio di JaredTS486 che utilizza le funzionalità native di Bash (comprese le versioni di Bash <4.0) per ottimizzare il suo approccio.
Ho cronometrato 1.000 iterazioni di questo approccio per una stringa piccola (25 caratteri) e una stringa più grande (445 caratteri), sia per le conversioni minuscole che maiuscole. Poiché le stringhe di test sono prevalentemente minuscole, le conversioni in minuscolo sono generalmente più veloci che in maiuscolo.
Ho confrontato il mio approccio con molte altre risposte in questa pagina che sono compatibili con Bash 3.2. Il mio approccio è molto più performante della maggior parte degli approcci documentati qui ed è persino più veloce che tr
in molti casi.
Ecco i risultati di temporizzazione per 1.000 iterazioni di 25 caratteri:
tr
minuscole; 3.81s per maiuscoleRisultati temporali per 1.000 iterazioni di 445 caratteri (costituito dal poema "The Robin" di Witter Bynner):
tr
minuscole; 4s per le maiuscoleSoluzione:
#!/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'approccio è semplice: mentre nella stringa di input sono presenti lettere maiuscole rimanenti, trova la successiva e sostituisci tutte le istanze di quella lettera con la sua variante minuscola. Ripetere fino a quando tutte le lettere maiuscole non vengono sostituite.
Alcune caratteristiche prestazionali della mia soluzione:
UCS
e LCS
può essere aumentato con caratteri aggiuntivi