primo carattere maiuscolo in una variabile con bash


Risposte:


148
foo="$(tr '[:lower:]' '[:upper:]' <<< ${foo:0:1})${foo:1}"

2
Nonostante sia più complesso della risposta con il punteggio migliore, questo in realtà fa esattamente questo: "il primo carattere maiuscolo in una variabile". La risposta con il punteggio migliore non ha risultati. Sembra che le risposte semplici siano votate più volentieri di quelle corrette?
Krzysztof Jabłoński,

15
@ KrzysztofJabłoński: In realtà, la "risposta con il miglior punteggio" di seguito produrrà gli stessi risultati di questa risposta in Bash 4. Questa risposta ha il sovraccarico di chiamare una subshell (un'altra shell), l'overhead di chiamare l'utilità 'tr' (un altro processo , non Bash), l'overhead dell'uso di here-doc / string (creazione di file temporanea) e utilizza due sostituzioni rispetto a quella con la migliore risposta ottenuta. Se è assolutamente necessario scrivere un codice legacy, prendere in considerazione l'utilizzo di una funzione anziché di una subshell.
Steve,

2
Questa risposta presuppone che l'input sia tutto minuscolo. Questa variante non ha presupposti: $ (tr '[: lower:]' '[: upper:]' <<< $ {foo: 0: 1}) $ (tr '[: upper:]' '[: lower: ] '<<< $ {foo: 1})
Itai Hanski il

5
@ItaiHanski L'OP non ha specificato cosa dovrebbe accadere ai personaggi rimanenti, solo il primo. Supposto che volevano cambiare notQuiteCamelin NotQuiteCamel. La tua variante ha l'effetto collaterale o costringe il restante a minuscole, al costo di raddoppiare il numero di sub shell e processi tr.
Jesse Chisholm,

3
@DanieleOrlando, vero, ma questa domanda non ha altri tag bash.
Charles Duffy,

314

Un modo con bash (versione 4+):

foo=bar
echo "${foo^}"

stampe:

Bar

2
C'è un contrario a questo?
CMCDragonkai,

44
@CMCDragonkai: per minuscole la prima lettera, utilizzare "${foo,}". Per minuscole tutte le lettere, utilizzare "${foo,,}". Per mettere in maiuscolo tutte le lettere, utilizzare "${foo^^}".
Steve,

1
L'ho notato per caso ${foo~}e ${foo~~}hanno lo stesso effetto di ${foo^}e ${foo^^}. Ma non ho mai visto quell'alternativa menzionata da nessuna parte.
marzo

5
questo non sembra funzionare su Mac. viene visualizzato il seguente errore:bad substitution
Toland Hon,

1
@TolandHon: come probabilmente hai già capito, dovrai aggiornare alla versione 4.x o provare un'altra soluzione se quella macchina non può essere aggiornata per qualche motivo.
Steve,

29

Un modo con sed:

echo "$(echo "$foo" | sed 's/.*/\u&/')"

stampe:

Bar

10
non funziona su MacOS10 Lion sed, sigh, il \ u si espande invece di essere un operatore.
vwvan,

2
@vwvan brew install coreutils gnu-sede segui le istruzioni per usare i comandi senza il prefisso g. Per quello che vale non ho mai voluto eseguire la versione OSX di questi comandi da quando ho ottenuto le versioni GNU.
Decano del

@vwvan: Sì, mi dispiace, sedin questo caso avrai bisogno di GNU
Steve,

2
@Dean: FWIW, non ho mai voluto eseguire OSX :-)
Steve,

5
Basta cambiarlo in sed 's/./\U&/e funzionerà su POSIX sed.
David Conrad,

24
$ foo="bar";
$ foo=`echo ${foo:0:1} | tr  '[a-z]' '[A-Z]'`${foo:1}
$ echo $foo
Bar

14

Ecco il modo "nativo" degli strumenti di testo:

#!/bin/bash

string="abcd"
first=`echo $string|cut -c1|tr [a-z] [A-Z]`
second=`echo $string|cut -c2-`
echo $first$second

finalmente qualcosa che funziona con una variabile e su Mac! Grazie!
OZZIE,

4
@DanieleOrlando, non portatile come si potrebbe sperare. tr [:lower:] [:upper:]è una scelta migliore se deve funzionare in una lingua / locale che incorpora lettere che non sono negli intervalli a-zo A-Z.
Charles Duffy,

8

Utilizzando solo awk

foo="uNcapItalizedstrIng"
echo $foo | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}'

risultato: cordoncino non capitalizzato
Alex Freshmann,

4

Può essere fatto anche in bash puro con bash-3.2:

# First, get the first character.
fl=${foo:0:1}

# Safety check: it must be a letter :).
if [[ ${fl} == [a-z] ]]; then
    # Now, obtain its octal value using printf (builtin).
    ord=$(printf '%o' "'${fl}")

    # Fun fact: [a-z] maps onto 0141..0172. [A-Z] is 0101..0132.
    # We can use decimal '- 40' to get the expected result!
    ord=$(( ord - 40 ))

    # Finally, map the new value back to a character.
    fl=$(printf '%b' '\'${ord})
fi

echo "${fl}${foo:1}"

come definire foo? Ci ho provato foo = $1ma ottengo solo-bash: foo: command not found
OZZIE il

1
@OZZIE, nessuno spazio attorno alle =assegnazioni. Questo è qualcosa che shellcheck.net troverà programmaticamente per te.
Charles Duffy,

Lo dimentico sempre degli script di shell ... solo il linguaggio in cui uno spazio (prima / dopo) conta ... sigh (python è almeno 4 se ricordo bene)
OZZIE

@OZZIE, deve avere importanza, perché se non importava, non si poteva passare =come argomento a un programma (come dovrebbe sapere se someprogram =è in esecuzione someprogramo assegnare a una variabile chiamata someprogram?)
Charles Duffy

3

Funziona anche questo ...

FooBar=baz

echo ${FooBar^^${FooBar:0:1}}

=> Baz
FooBar=baz

echo ${FooBar^^${FooBar:1:1}}

=> bAz
FooBar=baz

echo ${FooBar^^${FooBar:2:2}}

=> baZ

E così via.

fonti:

Inroductions / Tutorial:


3

Per scrivere in maiuscolo solo la prima parola:

foo='one two three'
foo="${foo^}"
echo $foo

O ne due tre


Per scrivere in maiuscolo ogni parola nella variabile:

foo="one two three"
foo=( $foo ) # without quotes
foo="${foo[@]^}"
echo $foo

O NE T wo T hree


(funziona in bash 4+)


foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) Risoluzione più breve per ogni parola. foo Now is "One Two Three"
vr286,

Come posso mettere in maiuscolo le prime 3 o 4 lettere in maiuscolo? Come pqrs-123-v1 a PQRS-123-v1 ? O puoi dire, tutte le lettere prima del primo trattino ...
Vicky Dev,

2

Soluzione alternativa e pulita per Linux e OSX, può essere utilizzata anche con variabili bash

python -c "print(\"abc\".capitalize())"

restituisce Abc


0

Questo ha funzionato per me:

Cerca tutti i file * php nella directory corrente e sostituisci il primo carattere di ciascun nome file con la lettera maiuscola:

ad esempio: test.php => Test.php

for f in *php ; do mv "$f" "$(\sed 's/.*/\u&/' <<< "$f")" ; done

4
La domanda originale era una stringa e non faceva alcun riferimento alla ridenominazione dei file.
AndySavage,

0

solo per divertimento eccoti qui:

foo="bar";    

echo $foo | awk '{$1=toupper(substr($1,0,1))substr($1,2)}1'
# or
echo ${foo^}
# or
echo $foo | head -c 1 | tr [a-z] [A-Z]; echo $foo | tail -c +2
# or
echo ${foo:1} | sed -e 's/^./\B&/'

0

Non esattamente quello che è stato chiesto, ma piuttosto utile

declare -u foo #When the variable is assigned a value, all lower-case characters are converted to upper-case.

foo=bar
echo $foo
BAR

E il contrario

declare -l foo #When the variable is assigned a value, all upper-case characters are converted to lower-case.

foo=BAR
echo $foo
bar

-1
first-letter-to-lower () {
        str="" 
        space=" " 
        for i in $@
        do
                if [ -z $(echo $i | grep "the\|of\|with" ) ]
                then
                        str=$str"$(echo ${i:0:1} | tr  '[A-Z]' '[a-z]')${i:1}$space" 
                else
                        str=$str${i}$space 
                fi
        done
        echo $str
}
first-letter-to-upper-xc () {
        v-first-letter-to-upper | xclip -selection clipboard
}
first-letter-to-upper () {
        str="" 
        space=" " 
        for i in $@
        do
                if [ -z $(echo $i | grep "the\|of\|with" ) ]
                then
                        str=$str"$(echo ${i:0:1} | tr  '[a-z]' '[A-Z]')${i:1}$space" 
                else
                        str=$str${i}$space 
                fi
        done
        echo $str
}

first-to-lower-xc () {v-first-letter-to-lower | xclip -selection appunti}


-7

Cosa succede se il primo carattere non è una lettera (ma una scheda, uno spazio e una virgoletta doppia evasa)? Faremmo meglio a provarlo fino a quando non troviamo una lettera! Così:

S='  \"ó foo bar\"'
N=0
until [[ ${S:$N:1} =~ [[:alpha:]] ]]; do N=$[$N+1]; done
#F=`echo ${S:$N:1} | tr [:lower:] [:upper:]`
#F=`echo ${S:$N:1} | sed -E -e 's/./\u&/'` #other option
F=`echo ${S:$N:1}
F=`echo ${F} #pure Bash solution to "upper"
echo "$F"${S:(($N+1))} #without garbage
echo '='${S:0:(($N))}"$F"${S:(($N+1))}'=' #garbage preserved

Foo bar
= \"Foo bar=

6
Si prega di scrivere un codice più pulito! ti mancano le citazioni dappertutto. Stai usando una sintassi obsoleta (backtick); stai usando la sintassi antiquata ( $[...]). Stai usando molte parentesi inutili. Stai assumendo che la stringa sia composta da caratteri dell'alfabeto latino (che ne dici di lettere accentate o lettere in altri alfabeti?). Hai lavorato moltissimo per rendere utilizzabile questo frammento! (e dal momento che stai usando regex, potresti anche usare regex per trovare la prima lettera, invece di un ciclo).
gniourf_gniourf

6
Penso che ti sbagli. È il commento obbligatorio che accompagna il voto negativo, spiegando tutti gli schemi e le idee sbagliate sbagliate della risposta. Per favore, impara dai tuoi errori (e prima ancora, cerca di capirli) invece di essere testardo. Essere un bravo ragazzo è anche incompatibile con la diffusione di cattive pratiche.
gniourf_gniourf

1
Oppure, se si utilizza Bash ≥4, non è necessario tr:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf

5
Questo codice è ancora gravemente rotto. Sta ancora usando i backtick invece della moderna sintassi di sostituzione; ha ancora virgolette senza pari; ha ancora le virgolette mancanti nei luoghi in cui contano ; ecc. Prova a inserire alcuni caratteri glob circondati da spazi bianchi nei tuoi dati di test, se non credi che quelle citazioni mancanti facciano la differenza e risolvi i problemi che shellcheck.net trova fino a quando questo codice non viene ripulito .
Charles Duffy,

2
Per quanto riguarda la lingua che hai citato da unix.stackexchange.com/questions/68694/… , quello che ti manca echo $fooè un esempio di una situazione in cui il parser si aspetta un elenco di parole ; così nel tuo echo ${F}, i contenuti di Fsono suddivisi in stringhe ed espansi glob. Questo è altrettanto vero per l' echo ${S:$N:1}esempio e tutto il resto. Vedi BashPitfalls # 14 .
Charles Duffy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.