Is er een manier om bashte converteren een tekenreeks in een tekenreeks in kleine letters?
Als ik bijvoorbeeld het volgende heb:
a="Hi all"
Ik wil het converteren naar:
"hi all"
Antwoord 1, autoriteit 100%
Er zijn verschillende manieren:
POSIX-standaard
tr
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
AWK
$ echo "$a" | awk '{print tolower($0)}'
hi all
Niet-POSIX
U kunt met de volgende voorbeelden te maken krijgen met overdraagbaarheidsproblemen:
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
Bash
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
Opmerking: YMMV op deze. Werkt niet voor mij (GNU bash versie 4.2.46 en 4.0.33 (en hetzelfde gedrag 2.05b.0 maar nocasematch is niet geïmplementeerd)) zelfs met het gebruik van shopt -u nocasematch;
. Als u die nocasematch uitschakelt, komt [[ “fooBaR” == “FOObar” ]] overeen met OK MAAR binnen de case wordt vreemd genoeg [b-z] onjuist vergeleken door [A-Z]. Bash is in de war door de dubbel-negatief (“unsetting nocasematch”)! 🙂
Antwoord 2, autoriteit 19%
In Bash 4:
Naar kleine letters
$ 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
Naar hoofdletters
$ 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 (niet gedocumenteerd, maar optioneel configureerbaar tijdens het compileren)
$ 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
Capitalize (niet gedocumenteerd, maar optioneel configureerbaar tijdens het compileren)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Titelgeval:
$ 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
Gebruik +
om een +
-kenmerk uit te schakelen. Bijvoorbeeld, declare +c string
. Dit heeft invloed op volgende toewijzingen en niet op de huidige waarde.
De +
opties veranderen het attribuut van de variabele, maar niet de inhoud. De hertoewijzingen in mijn voorbeelden werken de inhoud bij om de wijzigingen te tonen.
Bewerken:
“Toggle eerste teken voor woord” toegevoegd (${var~}
) zoals voorgesteld door ghostdog74.
Bewerken:tilde-gedrag gecorrigeerd om overeen te komen met Bash 4.3.
Antwoord 3, autoriteit 5%
echo "Hi All" | tr "[:upper:]" "[:lower:]"
Antwoord 4, autoriteit 4%
tr:
a="$(tr [A-Z] [a-z] <<< "$a")"
AWK:
{ print tolower($0) }
sed:
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
Antwoord 5, autoriteit 2%
Ik weet dat dit een ouderwets bericht is, maar ik heb dit antwoord voor een andere site gemaakt, dus ik dacht ik post het hier:
BOVENSTE -> lager:
gebruik python:
b=`echo "print '$a'.lower()" | python`
Of Robijn:
b=`echo "print '$a'.downcase" | ruby`
Of Perl:
b=`perl -e "print lc('$a');"`
Of PHP:
b=`php -r "print strtolower('$a');"`
Of Awk:
b=`echo "$a" | awk '{ print tolower($1) }'`
Of Sed:
b=`echo "$a" | sed 's/./\L&/g'`
Of Bash 4:
b=${a,,}
Of NodeJS:
b=`node -p "\"$a\".toLowerCase()"`
U kunt ook dd
gebruiken:
b=`echo "$a" | dd conv=lcase 2> /dev/null`
lager -> BOVENSTE:
gebruik python:
b=`echo "print '$a'.upper()" | python`
Of Robijn:
b=`echo "print '$a'.upcase" | ruby`
of perl:
b=`perl -e "print uc('$a');"`
of php:
b=`php -r "print strtoupper('$a');"`
of awk:
b=`echo "$a" | awk '{ print toupper($1) }'`
of sed:
b=`echo "$a" | sed 's/./\U&/g'`
of bash 4:
b=${a^^}
of nodejs:
b=`node -p "\"$a\".toUpperCase()"`
U kunt ook dd
:
gebruiken
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Ook wanneer u ‘Shell’ zegt, ik neem aan dat u bedoelt Bash
, maar als u zsh
kunt gebruiken, is het net zo eenvoudig als
b=$a:l
Voor kleine letters en
b=$a:u
voor hoofdletters.
Antwoord 6
in zsh:
echo $a:u
Ik hou van ZSH!
Antwoord 7
GNU gebruiken sed
:
sed 's/.*/\L&/'
Voorbeeld:
$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed 's/.*/\L&/')
$ echo "$foo"
some string
Antwoord 8
Pre Bash 4.0
Bash Verlaag de hoofdletters van een tekenreeks en wijs deze toe aan variabele
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
Antwoord 9
U kunt dit proberen
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/
Antwoord 10
Voor een standaard shell (zonder bashisms) die alleen ingebouwde elementen gebruikt:
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}"
}
En voor hoofdletters:
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}"
}
Antwoord 11
In bash 4 kunt u gebruik maken
Voorbeeld:
A="HELLO WORLD"
typeset -l A=$A
Antwoord 12
bash 5.1 biedt een eenvoudige manier om dit met de L
parameter transformatie:
${var@L}
Dus je kunt bijvoorbeeld zeggen:
$ v="heLLo"
$ echo "${v@L}"
hello
U kunt ook hoofdletters uitvoeren met U
:
$ v="hello"
$ echo "${v@U}"
HELLO
en hoofdletter de eerste letter met U
:
$ v="hello"
$ echo "${v@U}"
HELLO
Antwoord 13
Reguliere expressie
Ik zou graag krediet willen nemen voor het commando dat ik wil delen, maar de waarheid is dat ik het heb verkregen voor mijn eigen gebruik van http: / /commandlinefu.com . Het heeft het voordeel dat als u cd
naar elke map binnen uw eigen woningmap is, die het ook is, alle bestanden en mappen in kleine letters recursief zal wijzigen, voorzichtig. Het is een briljante opdrachtregel-fix en vooral handig voor die multiteuses van albums die u op uw drive hebt opgeslagen.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
U kunt een map opgeven in plaats van de punt (.) Na de vondst die de huidige map of het volledige pad aangeeft.
Ik hoop dat deze oplossing nuttig zal zijn. Het enige dat dit commando niet doet, is spaties vervangen door onderstrepingstekens – ach, een andere keer misschien.
Antwoord 14
Hoofdlettergebruik wordt alleen voor alfabetten omgezet. Dit zou dus netjes moeten werken.
Ik concentreer me op het omzetten van alfabetten tussen a-z van hoofdletters naar kleine letters. Alle andere tekens moeten gewoon in stdout worden afgedrukt zoals het is…
Converteert alle tekst in pad/naar/bestand/bestandsnaam binnen a-z bereik naar A-Z
Voor het converteren van kleine letters naar hoofdletters
cat path/to/file/filename | tr 'a-z' 'A-Z'
Voor het omzetten van hoofdletters naar kleine letters
cat path/to/file/filename | tr 'a-z' 'A-Z'
Bijvoorbeeld
bestandsnaam:
my name is xyz
wordt geconverteerd naar:
my name is xyz
Voorbeeld 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Voorbeeld 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Antwoord 15
Veel antwoorden met externe programma’s, die niet echt Bash
gebruiken.
Als je weet dat je Bash4 beschikbaar hebt, moet je gewoon de notatie ${VAR,,}
gebruiken (het is gemakkelijk en cool). Voor Bash voor 4 (mijn Mac gebruikt bijvoorbeeld nog steeds Bash 3.2). Ik heb de gecorrigeerde versie van het antwoord van @ghostdog74 gebruikt om een meer draagbare versie te maken.
Eentje die je lowercase 'my STRING'
kunt noemen en een kleine versie kunt krijgen. Ik heb opmerkingen gelezen over het instellen van het resultaat op een var, maar dat is niet echt draagbaar in Bash
, omdat we geen strings kunnen retourneren. Printen is de beste oplossing. Makkelijk vast te leggen met iets als var="$(lowercase $str)"
.
Hoe dit werkt
De manier waarop dit werkt is door de ASCII integer-representatie van elke char op te halen met printf
en dan adding 32
if upper-to->lower
, of subtracting 32
als lower-to->upper
. Gebruik vervolgens opnieuw printf
om het getal weer om te zetten naar een char. Van 'A' -to-> 'a'
we hebben een verschil van 32 tekens.
printf
gebruiken om uit te leggen:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
En dit is de werkende versie met voorbeelden.
Let op de opmerkingen in de code, omdat ze veel dingen uitleggen:
#!/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
En de resultaten na het uitvoeren van dit:
$ ./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!
Dit zou echter alleen moeten werken voor ASCII-tekens.
Voor mij is het prima, omdat ik weet dat ik er alleen ASCII-tekens aan zal doorgeven.
Ik gebruik dit bijvoorbeeld voor enkele hoofdletterongevoelige CLI-opties.
Antwoord 16
Eenvoudige manier
echo "Hi all" | awk '{ print tolower($0); }'
Antwoord 17
Als je v4 gebruikt, is dit ingebakken. Zo niet, dan is hier een eenvoudige, breed toepasbareoplossing. Andere antwoorden (en opmerkingen) in deze thread waren heel nuttig bij het maken van de onderstaande code.
# 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:] )\'
}
Opmerkingen:
- Doen:
a="Hi All"
en dan:lcase a
doet hetzelfde als:a=$( echolcase "Hi All" )
- In de lcase-functie zorgt het gebruik van
${!1//\'/"'\''"}
in plaats van${!1}
ervoor dat dit werkt zelfs als de string aanhalingstekens heeft.
Antwoord 18
Dit is een veel snellere variant van de JaredTS486’s approachdie gebruikmaakt van native Bash-mogelijkheden (inclusief Bash versies <4.0) om zijn aanpak te optimaliseren.
Ik heb 1000 iteraties van deze aanpak voor een kleine string (25 tekens) en een grotere reeks (445 tekens), zowel voor kleine letters als in hoofdletters). Aangezien de teststrings overwegend kleine letters zijn, zijn conversies naar kleine letters in het algemeen sneller dan in hoofdletters.
Ik heb mijn aanpak vergeleken met verschillende andere antwoorden op deze pagina die compatibel is met bash 3.2. Mijn aanpak is veel belangrijker dan de meeste benaderingen die hier worden gedocumenteerd en is nog sneller dan tr
in verschillende gevallen.
Hier zijn de timingresultaten voor 1.000 iteraties van 25 tekens:
- 0.46S voor mijn benadering van kleine letters; 0.96S voor hoofdletters
- 1.16S voor orwellophile’s aanpak naar kleine letters; 1,59s voor hoofdletters
- 3.67S voor
tr
NAAR KWERLAS; 3.81S voor hoofdletters - 11.12S voor ghostdog74’s aanpak naar kleine letters; 31.41S voor hoofdletters
- 26.25S voor technosaurus ‘nadering naar kleine letters; 26.21S voor hoofdletters
- 25.06s voor jaredts486’s aanpak naar kleine letters; 27.04S voor hoofdletters
Timingresultaten voor 1.000 iteraties van 445 tekens (bestaande uit het gedicht “The Robin” door Witter Bynner):
- 2S voor mijn benadering van kleine letters; 12s voor hoofdletters
- 4s voor
tr
naar kleine letters; 4s voor hoofdletters - 20s voor orwellophile’s aanpak naar kleine letters; 29s voor hoofdletters
- 75s voor ghostdog74’sbenadering van kleine letters; 669s voor hoofdletters. Het is interessant om op te merken hoe dramatisch het prestatieverschil is tussen een test met overheersende overeenkomsten versus een test met overheersende missers
- 467s voor technosaurus’ approachnaar kleine letters; 449s voor hoofdletters
- 660s voor JaredTS486’s approachnaar kleine letters; 660s voor hoofdletters. Het is interessant om op te merken dat deze aanpak continue paginafouten (memory swapping) in Bash genereerde
Oplossing:
#!/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}"
}
De aanpak is eenvoudig: terwijl de invoerreeks nog hoofdletters bevat, zoek de volgende en vervang alle instanties van die letter door de kleine lettervariant. Herhaal dit totdat alle hoofdletters zijn vervangen.
Enkele prestatiekenmerken van mijn oplossing:
- Gebruikt alleen in de shell ingebouwde hulpprogramma’s, waardoor de overhead van het aanroepen van externe binaire hulpprogramma’s in een nieuw proces wordt vermeden
- Vermijdt sub-shells, die prestatiestraffen opleveren
- Gebruikt shell-mechanismen die zijn gecompileerd en geoptimaliseerd voor prestaties, zoals globale vervanging van strings binnen variabelen, trimmen van variabele achtervoegsels en zoeken en matchen met regex. Deze mechanismen zijn veel sneller dan handmatig herhalen via strings
- Loopt alleen het aantal keren dat nodig is voor het aantal unieke overeenkomende tekens dat moet worden geconverteerd. Als u bijvoorbeeld een tekenreeks met drie verschillende hoofdletters naar kleine letters wilt converteren, zijn slechts 3 lus-iteraties nodig. Voor het vooraf geconfigureerde ASCII-alfabet is het maximale aantal lusiteraties 26
UCS
enLCS
kunnen worden aangevuld met extra tekens
Antwoord 19
Voor Bash-versies ouder dan 4.0 zou deze versie het snelst moeten zijn (omdat het geen fork /execalle commando’s):
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"
}
technosaurus’s antwoordhad potentieel ook, hoewel het voor mij wel goed liep.
Antwoord 20
Ondanks hoe oud deze vraag is en vergelijkbaar met dit antwoord door Technosaurus . Ik had een harde tijd vinden van een oplossing die overdraagbaar is tussen de meeste platforms was (die ik gebruik) alsook oudere versies van bash. Ik heb ook al gefrustreerd met arrays, functies en het gebruik van prints, echo’s en tijdelijke bestanden triviale variabelen op te halen. Dit werkt heel goed voor mij tot nu toe dacht ik dat ik zou delen.
Mijn belangrijkste testen omgevingen zijn:
- GNU bash, versie 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
- GNU bash, versie 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
Eenvoudige C-stijl voor lus te herhalen door de strijkers.
Voor de lijn hieronder als je niet iets als dit eerder gezien
dit is waar ik dit geleerd. In dit geval de lijn controleert of de char $ {ingang: $ i: 1} (kleine letters) bestaat in ingang en zo vervangen door het gegeven char $ {UCS: $ j: 1} (hoofdletters) en opslaat terug naar ingang.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Antwoord 21
Om de getransformeerde string in een variabele op te slaan. Volgend werkte voor mij –
$SOURCE_NAME
naar $TARGET_NAME
TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"