Gibt es einen Weg hinein Bash einen String in einen Kleinbuchstaben umwandeln?
Zum Beispiel, wenn ich habe:
a="Hi all"
Ich möchte es konvertieren in:
"hi all"
Gibt es einen Weg hinein Bash einen String in einen Kleinbuchstaben umwandeln?
Zum Beispiel, wenn ich habe:
a="Hi all"
Ich möchte es konvertieren in:
"hi all"
Antworten:
Es gibt verschiedene Möglichkeiten:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
Bei den folgenden Beispielen können Portabilitätsprobleme auftreten:
$ 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
Hinweis: YMMV in diesem Fall. Funktioniert bei mir nicht (GNU Bash Version 4.2.46 und 4.0.33 (und gleiches Verhalten 2.05b.0, aber Nocasematch ist nicht implementiert)), selbst bei Verwendung shopt -u nocasematch;
. Das Deaktivieren dieser Nichtübereinstimmung führt dazu, dass [["fooBaR" == "FOObar"]] mit OK übereinstimmt, ABER im Fall, dass [bz] seltsamerweise mit [AZ] falsch übereinstimmt. Bash wird durch das Doppel-Negativ verwirrt ("Nocasematch nicht setzen")! :-)
word="Hi All"
wie die anderen Beispiele machen, wird es ha
nicht zurückgegeben hi all
. Es funktioniert nur für Großbuchstaben und überspringt die bereits in Kleinbuchstaben geschriebenen Buchstaben.
tr
und awk
angegeben sind.
tr '[:upper:]' '[:lower:]'
verwendet das aktuelle Gebietsschema, um Groß- / Kleinbuchstaben zu ermitteln, sodass es mit Gebietsschemas funktioniert, die Buchstaben mit diakritischen Zeichen verwenden.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
In Bash 4:
In Kleinbuchstaben
$ 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
In Großbuchstaben
$ 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
Umschalten (undokumentiert, aber zur Kompilierungszeit optional konfigurierbar)
$ 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
Großschreibung (undokumentiert, aber zur Kompilierungszeit optional konfigurierbar)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Titelfall:
$ 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
declare
Verwenden Sie zum Deaktivieren eines Attributs +
. Zum Beispiel declare +c string
. Dies wirkt sich auf nachfolgende Zuordnungen und nicht auf den aktuellen Wert aus.
Die declare
Optionen ändern das Attribut der Variablen, nicht jedoch den Inhalt. Die Neuzuweisungen in meinen Beispielen aktualisieren den Inhalt, um die Änderungen anzuzeigen.
Bearbeiten:
Es wurde "erstes Zeichen nach Wort umschalten " ( ${var~}
) hinzugefügt, wie von ghostdog74 vorgeschlagen .
Bearbeiten: Das Tilde-Verhalten wurde korrigiert, um mit Bash 4.3 übereinzustimmen.
string="łódź"; echo ${string~~}
Gibt also "ŁÓDŹ" zurück, gibt aber echo ${string^^}
"łóDź" zurück. Auch in LC_ALL=pl_PL.utf-8
. Das ist Bash 4.2.24.
en_US.UTF-8
. Es ist ein Fehler und ich habe ihn gemeldet.
echo "$string" | tr '[:lower:]' '[:upper:]'
. Es wird wahrscheinlich den gleichen Fehler aufweisen. Das Problem ist also zumindest teilweise nicht das von Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr
funktioniert bei mir nicht für Nicht-ACII-Zeichen. Ich habe korrekte Gebietsschemasätze und Gebietsschemadateien generiert. Haben Sie eine Idee, was ich falsch machen könnte?
[:upper:]
benötigt?
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"
sieht für mich am einfachsten aus. Ich bin noch ein Anfänger ...
sed
Lösung nachdrücklich . Ich habe in einer Umgebung gearbeitet, die es aus irgendeinem Grund nicht gibt, tr
aber ich habe noch kein System ohne gefunden sed
. Außerdem habe ich die meiste Zeit, in der ich dies tun möchte, sed
sowieso etwas anderes getan, damit ich es verketten kann die Befehle zusammen zu einer einzigen (langen) Anweisung.
tr [A-Z] [a-z] A
kann die Shell eine Dateinamenerweiterung durchführen, wenn Dateinamen aus einem einzelnen Buchstaben bestehen oder ein Nullgob festgelegt ist. tr "[A-Z]" "[a-z]" A
wird sich richtig verhalten.
sed
tr [A-Z] [a-z]
in fast allen Ländereinstellungen falsch ist. Im en-US
Gebietsschema A-Z
ist beispielsweise das Intervall angegeben AaBbCcDdEeFfGgHh...XxYyZ
.
Ich weiß, dass dies ein alter Beitrag ist, aber ich habe diese Antwort für eine andere Website gegeben, also dachte ich, ich würde sie hier veröffentlichen:
UPPER -> lower : Verwenden Sie Python:
b=`echo "print '$a'.lower()" | python`
Oder Ruby:
b=`echo "print '$a'.downcase" | ruby`
Oder Perl (wahrscheinlich mein Favorit):
b=`perl -e "print lc('$a');"`
Oder PHP:
b=`php -r "print strtolower('$a');"`
Oder Awk:
b=`echo "$a" | awk '{ print tolower($1) }'`
Oder Sed:
b=`echo "$a" | sed 's/./\L&/g'`
Oder Bash 4:
b=${a,,}
Oder NodeJS, wenn Sie es haben (und ein bisschen verrückt sind ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Sie könnten auch verwenden dd
(aber ich würde nicht!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
niedriger -> OBER :
Verwenden Sie Python:
b=`echo "print '$a'.upper()" | python`
Oder Ruby:
b=`echo "print '$a'.upcase" | ruby`
Oder Perl (wahrscheinlich mein Favorit):
b=`perl -e "print uc('$a');"`
Oder PHP:
b=`php -r "print strtoupper('$a');"`
Oder Awk:
b=`echo "$a" | awk '{ print toupper($1) }'`
Oder Sed:
b=`echo "$a" | sed 's/./\U&/g'`
Oder Bash 4:
b=${a^^}
Oder NodeJS, wenn Sie es haben (und ein bisschen verrückt sind ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Sie könnten auch verwenden dd
(aber ich würde nicht!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Auch wenn Sie "Shell" sagen, nehme ich an, Sie meinen, bash
aber wenn Sie es verwenden können, ist zsh
es so einfach wie
b=$a:l
für Kleinbuchstaben und
b=$a:u
für Großbuchstaben.
a
ein einfaches Anführungszeichen enthält, haben Sie nicht nur ein fehlerhaftes Verhalten, sondern auch ein ernstes Sicherheitsproblem.
In zsh:
echo $a:u
Muss ich lieben zsh!
echo ${(C)a} #Upcase the first char only
Pre Bash 4.0
Bash Senken Sie die Groß- / Kleinschreibung einer Zeichenfolge und weisen Sie sie einer Variablen zu
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echo
und Rohre: Verwendung$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Für eine Standard-Shell (ohne Bashismen), die nur eingebaute verwendet:
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}"
}
Und für Großbuchstaben:
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}
sind ein Baschismus.
Sie können dies versuchen
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/
Ich möchte den Befehl, den ich teilen möchte, gutschreiben, aber die Wahrheit ist, dass ich ihn für meinen eigenen Gebrauch von http://commandlinefu.com erhalten habe . Es hat den Vorteil, dass wenn Sie cd
in ein Verzeichnis in Ihrem eigenen Home-Ordner wechseln, alle Dateien und Ordner rekursiv in Kleinbuchstaben geändert werden, verwenden Sie diese bitte mit Vorsicht. Es ist eine brillante Befehlszeilenkorrektur und besonders nützlich für die Vielzahl von Alben, die Sie auf Ihrem Laufwerk gespeichert haben.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Sie können anstelle des Punkts (.) Nach der Suche ein Verzeichnis angeben, das das aktuelle Verzeichnis oder den vollständigen Pfad angibt.
Ich hoffe, diese Lösung erweist sich als nützlich. Das einzige, was dieser Befehl nicht tut, ist, Leerzeichen durch Unterstriche zu ersetzen - na ja, vielleicht ein anderes Mal.
prename
von perl
: dpkg -S "$(readlink -e /usr/bin/rename)"
gibtperl: /usr/bin/prename
Viele Antworten mit externen Programmen, die nicht wirklich verwendet werden Bash
.
Wenn Sie wissen, dass Sie Bash4 zur Verfügung haben, sollten Sie wirklich nur die ${VAR,,}
Notation verwenden (es ist einfach und cool). Für Bash vor 4 (Mein Mac verwendet zum Beispiel immer noch Bash 3.2). Ich habe die korrigierte Version der Antwort von @ ghostdog74 verwendet, um eine portablere Version zu erstellen.
Eine, die Sie anrufen lowercase 'my STRING'
und eine Kleinbuchstabenversion erhalten können. Ich habe Kommentare zum Setzen des Ergebnisses auf eine Variable gelesen, aber das ist nicht wirklich portabel Bash
, da wir keine Zeichenfolgen zurückgeben können. Drucken ist die beste Lösung. Einfach mit so etwas zu erfassen var="$(lowercase $str)"
.
Wie das funktioniert
Dies funktioniert, indem die ASCII-Ganzzahldarstellung jedes Zeichens mit printf
und dann adding 32
if upper-to->lower
oder subtracting 32
if abgerufen wird lower-to->upper
. Verwenden Sie dann printf
erneut, um die Zahl wieder in ein Zeichen umzuwandeln. Von haben 'A' -to-> 'a'
wir einen Unterschied von 32 Zeichen.
Verwenden printf
, um zu erklären:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
Und dies ist die Arbeitsversion mit Beispielen.
Bitte beachten Sie die Kommentare im Code, da sie viele Dinge erklären:
#!/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
Und die Ergebnisse nach dem Ausführen:
$ ./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!
Dies sollte jedoch nur für ASCII-Zeichen funktionieren .
Für mich ist es in Ordnung, da ich weiß, dass ich nur ASCII-Zeichen weitergeben werde.
Ich verwende dies zum Beispiel für einige CLI-Optionen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird.
Das Konvertieren von Groß- und Kleinschreibung erfolgt nur für Alphabete. Das sollte also ordentlich funktionieren.
Ich konzentriere mich auf die Konvertierung von Alphabeten zwischen az von Groß- in Kleinbuchstaben. Alle anderen Zeichen sollten so wie sie sind in stdout gedruckt werden ...
Konvertiert den gesamten Text im Pfad / in / Datei / Dateiname im Az-Bereich in AZ
Zum Konvertieren von Kleinbuchstaben in Großbuchstaben
cat path/to/file/filename | tr 'a-z' 'A-Z'
Zum Konvertieren von Groß- in Kleinbuchstaben
cat path/to/file/filename | tr 'A-Z' 'a-z'
Zum Beispiel,
Dateiname:
my name is xyz
wird konvertiert zu:
MY NAME IS XYZ
Beispiel 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Beispiel 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Wenn Sie v4 verwenden, ist dies eingebrannt . Wenn nicht, finden Sie hier eine einfache, allgemein anwendbare Lösung. Andere Antworten (und Kommentare) zu diesem Thread waren beim Erstellen des folgenden Codes sehr hilfreich.
# 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:] )\'
}
Anmerkungen:
a="Hi All"
und dann: lcase a
wird das Gleiche tun wie:a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
anstelle von, ${!1}
dass dies auch dann funktioniert, wenn die Zeichenfolge Anführungszeichen enthält.Für Bash-Versionen vor 4.0 sollte diese Version am schnellsten sein (da keine Befehle gegabelt / ausgeführt werden):
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"
}
Die Antwort von technosaurus hatte auch Potenzial, obwohl sie für mich richtig lief.
Trotz des Alters dieser Frage und ähnlich dieser Antwort von Technosaurus . Es fiel mir schwer, eine Lösung zu finden, die auf den meisten Plattformen (die ich verwende) sowie auf älteren Versionen von Bash portabel war. Ich war auch frustriert über Arrays, Funktionen und die Verwendung von Ausdrucken, Echos und temporären Dateien zum Abrufen trivialer Variablen. Das funktioniert sehr gut für mich, bis jetzt dachte ich, ich würde teilen. Meine Haupttestumgebungen sind:
- GNU Bash, Version 4.1.2 (1) -Veröffentlichung (x86_64-redhat-linux-gnu)
- GNU Bash, Version 3.2.57 (1) -Veröffentlichung (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
Einfache C-artige for-Schleife zum Durchlaufen der Zeichenfolgen. Für die folgende Zeile, wenn Sie so etwas noch nicht gesehen haben, habe ich dies hier gelernt . In diesem Fall prüft die Zeile, ob das Zeichen $ {input: $ i: 1} (Kleinbuchstaben) in der Eingabe vorhanden ist, und ersetzt es in diesem Fall durch das angegebene Zeichen $ {ucs: $ j: 1} (Großbuchstaben) und speichert es zurück in die Eingabe.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Dies ist eine weitaus schnellere Variante des Ansatzes von JaredTS486 , bei dem native Bash-Funktionen (einschließlich Bash-Versionen <4.0) verwendet werden, um seinen Ansatz zu optimieren.
Ich habe 1.000 Iterationen dieses Ansatzes für eine kleine Zeichenfolge (25 Zeichen) und eine größere Zeichenfolge (445 Zeichen) zeitlich festgelegt, sowohl für Konvertierungen in Klein- als auch in Großbuchstaben. Da die Testzeichenfolgen überwiegend in Kleinbuchstaben geschrieben sind, sind Konvertierungen in Kleinbuchstaben im Allgemeinen schneller als in Großbuchstaben.
Ich habe meinen Ansatz mit mehreren anderen Antworten auf dieser Seite verglichen, die mit Bash 3.2 kompatibel sind. Mein Ansatz ist weitaus leistungsfähiger als die meisten hier dokumentierten Ansätze und sogar schneller als tr
in einigen Fällen.
Hier sind die Timing-Ergebnisse für 1.000 Iterationen mit 25 Zeichen:
tr
Kleinbuchstaben; 3,81s für GroßbuchstabenTiming-Ergebnisse für 1.000 Iterationen von 445 Zeichen (bestehend aus dem Gedicht "The Robin" von Witter Bynner):
tr
Kleinbuchstaben; 4s für GroßbuchstabenLösung:
#!/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}"
}
Der Ansatz ist einfach: Während in der Eingabezeichenfolge noch Großbuchstaben vorhanden sind, suchen Sie den nächsten und ersetzen Sie alle Instanzen dieses Buchstabens durch seine Kleinbuchstabenvariante. Wiederholen, bis alle Großbuchstaben ersetzt sind.
Einige Leistungsmerkmale meiner Lösung:
UCS
und LCS
kann mit zusätzlichen Zeichen erweitert werden