erstes Großbuchstaben in einer Variablen mit Bash

162

Ich möchte nur das erste Zeichen in meiner Zeichenfolge mit Bash in Großbuchstaben schreiben.

foo="bar";

//uppercase first character

echo $foo;

sollte "Bar" drucken;

chovy
quelle
1
Es ist kein genaues Duplikat, aber viele der unter Konvertieren von Zeichenfolgen in Kleinbuchstaben in Bash-Shell-Skripten beschriebenen Techniken können auch auf dieses Problem angewendet werden.
pjh

Antworten:

148
foo="$(tr '[:lower:]' '[:upper:]' <<< ${foo:0:1})${foo:1}"
Michael Hoffman
quelle
2
Obwohl diese Antwort komplexer ist als die am besten bewertete, macht sie genau das: 'erstes Zeichen in Großbuchstaben in einer Variablen'. Die am besten bewertete Antwort hat diese Ergebnisse nicht. Sieht so aus, als würden einfache Antworten eher positiv bewertet als die richtigen?
Krzysztof Jabłoński
15
@ KrzysztofJabłoński: Tatsächlich führt die unten stehende "am besten bewertete Antwort" zu denselben Ergebnissen wie diese Antwort unter Bash 4. Diese Antwort hat den Aufwand, eine Subshell (eine andere Shell) aufzurufen, den Aufwand, das Dienstprogramm 'tr' (einen anderen Prozess) aufzurufen , nicht Bash), der Aufwand für die Verwendung eines Here-Docs / Strings (temporäre Dateierstellung) und zwei Substitutionen im Vergleich zur Antwort der am besten bewerteten Antwort. Wenn Sie unbedingt Legacy-Code schreiben müssen, sollten Sie eine Funktion anstelle einer Subshell verwenden.
Steve
2
Diese Antwort setzt voraus, dass die Eingabe nur in Kleinbuchstaben erfolgt. Diese Variante hat keine Annahmen: $ (tr '[: unter:]' '[: oben:]' <<< $ {foo: 0: 1}) $ (tr '[: oben:]' '[: unten: ] '<<< $ {foo: 1})
Itai Hanski
5
@ItaiHanski Das OP hat nicht angegeben, was mit den verbleibenden Zeichen geschehen soll, sondern nur mit dem ersten. Vermeintliche sie wollten sich ändern notQuiteCamelin NotQuiteCamel. Ihre Variante hat den Nebeneffekt oder zwingt den Rest in Kleinbuchstaben - auf Kosten der Verdoppelung der Anzahl von Unterschalen und Tr-Prozessen.
Jesse Chisholm
3
@ DanieleOrlando, stimmt, aber diese Frage hat keine anderen Tags als bash.
Charles Duffy
313

Ein Weg mit Bash (Version 4+):

foo=bar
echo "${foo^}"

Drucke:

Bar
Steve
quelle
2
Gibt es ein Gegenteil dazu?
CMCDragonkai
44
@CMCDragonkai: Um den ersten Buchstaben in Kleinbuchstaben zu schreiben, verwenden Sie "${foo,}". Verwenden Sie, um alle Buchstaben in Kleinbuchstaben zu schreiben "${foo,,}". Verwenden Sie, um alle Buchstaben in Großbuchstaben zu schreiben "${foo^^}".
Steve
1
Ich habe das versehentlich bemerkt ${foo~}und ${foo~~}habe den gleichen Effekt wie ${foo^}und ${foo^^}. Aber ich habe diese Alternative nie erwähnt.
Mivk
5
Dies scheint auf Macs nicht zu funktionieren. Erhalten des folgenden Fehlers:bad substitution
Toland Hon
1
@ TolandHon: Wie Sie wahrscheinlich bereits herausgefunden haben, müssen Sie auf Version 4.x aktualisieren oder eine andere Lösung ausprobieren, wenn dieser Computer aus irgendeinem Grund nicht aktualisiert werden kann.
Steve
29

Ein Weg mit sed:

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

Drucke:

Bar
Steve
quelle
10
funktioniert nicht unter MacOS10 Lion sed, seufz, das \ u erweitert sich zu u, anstatt ein Operator zu sein.
Vwvan
2
@vwvan brew install coreutils gnu-sedund befolgen Sie die Anweisungen, um die Befehle ohne Präfix zu verwenden g. Für das, was es wert ist, wollte ich die OSX-Version dieser Befehle seit dem Erhalt der GNU-Versionen nie mehr ausführen.
Dean
@vwvan: Ja, sorry, Sie werden GNU sedin diesem Fall brauchen
Steve
2
@ Dean: FWIW, ich wollte noch nie OSX ausführen :-)
Steve
5
Ändern Sie sed 's/./\U&/es einfach in und es wird auf POSIX sed funktionieren.
David Conrad
24
$ foo="bar";
$ foo=`echo ${foo:0:1} | tr  '[a-z]' '[A-Z]'`${foo:1}
$ echo $foo
Bar
Majid Laissi
quelle
14

Hier ist die "native" Art der Textwerkzeuge:

#!/bin/bash

string="abcd"
first=`echo $string|cut -c1|tr [a-z] [A-Z]`
second=`echo $string|cut -c2-`
echo $first$second
Equin0x
quelle
Endlich etwas, das mit einer Variablen und auf dem Mac funktioniert! Danke dir!
OZZIE
4
@ DanieleOrlando, nicht so tragbar, wie man hoffen könnte. tr [:lower:] [:upper:]ist eine bessere Wahl, wenn es in Sprachen / Gebietsschemas mit Buchstaben arbeiten muss, die nicht in den Bereichen a-zoder A-Zliegen.
Charles Duffy
8

Nur awk verwenden

foo="uNcapItalizedstrIng"
echo $foo | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}'
toske
quelle
Ergebnis: Uncapitalizedstring
Alex Freshmann
4

Es kann auch in reinem Bash mit Bash-3.2 durchgeführt werden:

# 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}"
Michał Górny
quelle
Wie definiere ich foo? Ich habe es versucht, foo = $1aber ich bekomme nur-bash: foo: command not found
OZZIE
1
@OZZIE, keine Leerzeichen um die =in Zuordnungen. Dies wird Shellcheck.net programmgesteuert für Sie finden.
Charles Duffy
Ich vergesse das immer über Shell-Skripte ... nur Sprache, in der ein Leerzeichen (vorher / nachher) wichtig ist ... seufz (Python ist mindestens 4, wenn ich mich richtig erinnere)
OZZIE
@OZZIE, es muss wichtig sein, denn wenn es nicht wichtig wäre, könnten Sie es nicht =als Argument an ein Programm übergeben (woher soll es wissen, ob someprogram =es ausgeführt someprogramwird oder einer Variablen mit dem Namen zugewiesen wird someprogram?)
Charles Duffy
3

Das funktioniert auch ...

FooBar=baz

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

=> Baz
FooBar=baz

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

=> bAz
FooBar=baz

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

=> baZ

Und so weiter.

Quellen:

Einführungen / Tutorials:

Zetaomegagon
quelle
3

Um nur das erste Wort groß zu schreiben:

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

O ne zwei drei


So schreiben Sie jedes Wort in der Variablen groß :

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

O ne T wo T drei


(funktioniert in Bash 4+)

Ole Lukøje
quelle
foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) Kürzere Auflösung für jedes Wort. foo Jetzt ist "Eins Zwei Drei"
vr286
2

Alternative und saubere Lösung für Linux und OSX, kann auch mit Bash-Variablen verwendet werden

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

gibt Abc zurück

Thomas Webber
quelle
0

Dieser hat für mich gearbeitet:

Suchen Sie nach allen * PHP-Dateien im aktuellen Verzeichnis und ersetzen Sie das erste Zeichen jedes Dateinamens durch Großbuchstaben:

zB: test.php => Test.php

for f in *php ; do mv "$f" "$(\sed 's/.*/\u&/' <<< "$f")" ; done
Shemeshey
quelle
4
Die ursprüngliche Frage war eine Zeichenfolge und bezog sich nicht auf das Umbenennen von Dateien.
AndySavage
0

Nur zum Spaß hier bist du:

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&/'
Freeman
quelle
0

Nicht genau das, was gefragt wurde, aber sehr hilfreich

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

foo=bar
echo $foo
BAR

Und das Gegenteil

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

foo=BAR
echo $foo
bar
Ivan
quelle
-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
}

erster Buchstabe zum unteren xc () {v-erster Buchstabe zum unteren | xclip -selection Zwischenablage}

user123456
quelle
-7

Was ist, wenn das erste Zeichen kein Buchstabe ist (sondern ein Tabulator, ein Leerzeichen und ein maskiertes Anführungszeichen)? Wir sollten es besser testen , bis wir einen Brief finden! So:

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=
Roger
quelle
6
Bitte schreiben Sie saubereren Code! Ihnen fehlen überall Zitate . Sie verwenden veraltete Syntax (Backticks). Sie verwenden eine veraltete Syntax ( $[...]). Sie verwenden viele nutzlose Klammern. Sie gehen davon aus, dass die Zeichenfolge aus Zeichen aus dem lateinischen Alphabet besteht (wie wäre es mit akzentuierten Buchstaben oder Buchstaben in anderen Alphabeten?). Sie haben viel Arbeit, um dieses Snippet nutzbar zu machen! (und da Sie Regex verwenden, können Sie auch den Regex verwenden, um den ersten Buchstaben anstelle einer Schleife zu finden).
gniourf_gniourf
6
Ich denke du liegst falsch. Es ist der obligatorische Kommentar, der die Abwertung begleitet und alle falschen Muster und Missverständnisse der Antwort erklärt. Bitte lernen Sie aus Ihren Fehlern (und versuchen Sie vorher, sie zu verstehen), anstatt hartnäckig zu sein. Ein guter Gefährte zu sein, ist auch nicht mit der Verbreitung schlechter Praktiken vereinbar.
gniourf_gniourf
1
Oder wenn Sie Bash ≥4 verwenden, brauchen Sie nicht tr:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf
5
Dieser Code ist immer noch stark defekt. Es werden immer noch Backticks anstelle der modernen Substitutionssyntax verwendet. es hat immer noch unübertroffene Zitate; es fehlen immer noch Anführungszeichen an Stellen, an denen sie tatsächlich eine Rolle spielen ; usw. Versuchen Sie, einige von Leerzeichen umgebene Glob-Zeichen in Ihre Testdaten einzufügen , wenn Sie nicht glauben, dass diese fehlenden Anführungszeichen einen Unterschied machen, und beheben Sie die Probleme, die shellcheck.net findet, bis dieser Code sauber angezeigt wird .
Charles Duffy
2
Was die Sprache betrifft , die Sie aus unix.stackexchange.com/questions/68694/… zitiert haben , so vermissen Sie echo $fooein Beispiel für eine Situation, in der der Parser eine Liste von Wörtern erwartet . In Ihrem Fall sind echo ${F}die Inhalte von FString-Split und Glob-Expanded. Das gilt auch für das echo ${S:$N:1}Beispiel und den Rest. Siehe BashPitfalls # 14 .
Charles Duffy