huruf besar pertama dalam variabel dengan bash

162

Saya ingin huruf besar hanya karakter pertama di string saya dengan bash.

foo="bar";

//uppercase first character

echo $foo;

harus mencetak "Bar";

kenyal
sumber
1
Ini bukan duplikat yang tepat, tetapi banyak teknik yang dijelaskan dalam Konversi string ke huruf kecil dalam skrip Bash shell juga dapat diterapkan untuk masalah ini.
pjh

Jawaban:

148
foo="$(tr '[:lower:]' '[:upper:]' <<< ${foo:0:1})${foo:1}"
Michael Hoffman
sumber
2
Meskipun lebih kompleks daripada jawaban skor terbaik, yang satu ini benar-benar melakukan hal itu: 'huruf pertama dalam variabel'. Jawaban skor terbaik tidak memiliki hasil itu. Sepertinya jawaban sederhana lebih dipilih secara sukarela daripada jawaban yang benar?
Krzysztof Jabłoński
15
@ KrzysztofJabłoński: Sebenarnya, "jawaban dengan skor terbaik" di bawah ini akan menghasilkan hasil yang sama dengan jawaban ini di bawah Bash 4. Jawaban ini memiliki overhead untuk memanggil subkulit (shell lain), overhead untuk memanggil utilitas 'tr' (proses lain , bukan Bash), overhead menggunakan di sini-doc / string (pembuatan file sementara) dan menggunakan dua substitusi dibandingkan dengan yang terbaik jawaban jawaban. Jika Anda benar-benar harus menulis kode lawas, pertimbangkan untuk menggunakan fungsi alih-alih subkulit.
Steve
2
Jawaban ini mengasumsikan input semua huruf kecil. Varian ini tidak memiliki asumsi: $ (tr '[: lebih rendah:]' '[: atas:]' <<< $ {foo: 0: 1}) $ (tr '[: atas:]' '[: lebih rendah: ] '<<< $ {foo: 1})
Itai Hanski
5
@ItaiHanski OP tidak menentukan apa yang harus terjadi pada karakter yang tersisa, hanya yang pertama. Seharusnya mereka ingin berubah notQuiteCamelmenjadi NotQuiteCamel. Varian Anda memiliki efek samping atau memaksa sisanya menjadi huruf kecil - dengan biaya menggandakan jumlah subkulit dan proses tr.
Jesse Chisholm
3
@DanieleOrlando, benar, tetapi pertanyaan ini tidak memiliki tag selain bash.
Charles Duffy
314

Satu arah dengan bash (versi 4+):

foo=bar
echo "${foo^}"

cetakan:

Bar
Steve
sumber
2
Apakah ada yang bertentangan dengan ini?
CMCDragonkai
44
@ CMCDragonkai: Untuk huruf kecil huruf pertama, gunakan "${foo,}". Untuk huruf kecil semua huruf, gunakan "${foo,,}". Untuk huruf besar semua huruf, gunakan "${foo^^}".
Steve
1
Saya tidak sengaja memperhatikan itu ${foo~}dan ${foo~~}memiliki efek yang sama seperti ${foo^}dan ${foo^^}. Tetapi saya tidak pernah melihat alternatif itu disebutkan di mana pun.
mivk
5
ini sepertinya tidak berfungsi pada Mac. mendapatkan kesalahan berikut:bad substitution
Toland Hon
1
@TolandHon: Karena Anda mungkin sudah berolahraga, Anda harus meningkatkan ke versi 4.x, atau mencoba solusi lain jika mesin itu tidak dapat ditingkatkan karena alasan tertentu.
Steve
29

Satu cara dengan sed:

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

Cetakan:

Bar
Steve
sumber
10
tidak berfungsi pada MacOS10 Lion, huh, \ u memperluas ke Anda alih-alih menjadi operator.
vwvan
2
@vwvan brew install coreutils gnu-seddan ikuti instruksi untuk menggunakan perintah tanpa awalan g. Untuk apa nilainya saya tidak pernah ingin menjalankan versi OSX dari perintah ini sejak mendapatkan versi GNU.
Dean
@vwvan: Ya, maaf, Anda membutuhkan GNU seddalam hal ini
Steve
2
@Dean: FWIW, saya tidak pernah ingin menjalankan OSX :-)
Steve
5
Cukup ubah sed 's/./\U&/dan akan berfungsi pada POSIX sed.
David Conrad
24
$ foo="bar";
$ foo=`echo ${foo:0:1} | tr  '[a-z]' '[A-Z]'`${foo:1}
$ echo $foo
Bar
Majid Laissi
sumber
14

Berikut ini cara alat teks "asli":

#!/bin/bash

string="abcd"
first=`echo $string|cut -c1|tr [a-z] [A-Z]`
second=`echo $string|cut -c2-`
echo $first$second
Equin0x
sumber
akhirnya sesuatu yang bekerja dengan variabel dan di Mac! Terima kasih!
OZZIE
4
@DanieleOrlando, tidak portabel seperti yang diharapkan. tr [:lower:] [:upper:]adalah pilihan yang lebih baik jika perlu bekerja dalam bahasa / lokal memasukkan huruf yang tidak ada dalam a-zatau A-Zrentang.
Charles Duffy
8

Hanya menggunakan awk

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

Ini dapat dilakukan dalam bash murni dengan bash-3.2 juga:

# 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
sumber
bagaimana cara mendefinisikan foo? Saya mencoba foo = $1tetapi saya hanya mendapatkan-bash: foo: command not found
OZZIE
1
@OZZIE, tidak ada spasi di sekitar =tugas dalam. Ini adalah sesuatu yang shellcheck.net akan temukan untuk Anda secara terprogram .
Charles Duffy
Saya selalu lupa bahwa tentang skrip shell .. hanya bahasa di mana satu spasi (sebelum / sesudah) penting ... sigh (python setidaknya 4 jika saya ingat dengan benar)
OZZIE
@OZZIE, itu memiliki untuk peduli, karena jika tidak masalah, Anda tidak bisa lulus =sebagai argumen untuk program (bagaimana cara seharusnya tahu jika someprogram =sedang berjalan someprogram, atau menugaskan ke variabel bernama someprogram?)
Charles Duffy
3

Ini juga berfungsi ...

FooBar=baz

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

=> Baz
FooBar=baz

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

=> bAz
FooBar=baz

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

=> baZ

Dan seterusnya.

Sumber:

Pengenalan / Tutorial:

zetaomegagon
sumber
3

Hanya menggunakan huruf kapital untuk kata pertama:

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

O ne dua tiga


Untuk mengkapitalisasi setiap kata dalam variabel:

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

O ne T wo T hree


(bekerja di bash 4+)

Ole Lukøje
sumber
foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) Resolusi lebih pendek untuk setiap kata. foo Sekarang adalah "One Two Three"
vr286
Bagaimana saya bisa menggunakan huruf besar 3 atau 4 pertama untuk huruf besar? Suka pqrs-123-v1 ke PQRS-123-v1 ? Atau Anda bisa mengatakan, semua huruf sebelum tanda hubung pertama ...
Vicky Dev
2

Alternatif dan solusi bersih untuk Linux dan OSX, dapat juga digunakan dengan variabel bash

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

mengembalikan Abc

Thomas Webber
sumber
0

Yang ini bekerja untuk saya:

Mencari semua * file php di direktori saat ini, dan ganti karakter pertama dari setiap nama file dengan huruf kapital:

misal: test.php => Test.php

for f in *php ; do mv "$f" "$(\sed 's/.*/\u&/' <<< "$f")" ; done
Shemeshey
sumber
4
Pertanyaan aslinya adalah string, dan tidak membuat referensi untuk mengubah nama file.
AndySavage
0

hanya untuk bersenang-senang di sini Anda berada:

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&/'
Warga kehormatan
sumber
0

Tidak persis apa yang diminta tetapi sangat membantu

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

foo=bar
echo $foo
BAR

Dan sebaliknya

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
sumber
-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-letter-to-lower-xc () {v-first-letter-to-lower | xclip-clipboard pilihan}

pengguna123456
sumber
-7

Bagaimana jika karakter pertama bukan huruf (tetapi tab, spasi, dan kutipan ganda yang lolos)? Lebih baik kita menguji itu sampai kita menemukan surat! Begitu:

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
sumber
6
Silakan tulis kode bersih! Anda kekurangan kutipan di semua tempat. Anda menggunakan sintaks yang usang (backticks); Anda menggunakan sintaks antiquated ( $[...]). Anda menggunakan banyak tanda kurung yang tidak berguna. Anda mengasumsikan bahwa string terdiri dari karakter dari alfabet latin (bagaimana dengan huruf aksentuasi, atau huruf dalam huruf lain?). Anda memiliki banyak pekerjaan untuk membuat cuplikan ini dapat digunakan! (dan karena Anda menggunakan regex, Anda mungkin juga menggunakan regex untuk menemukan huruf pertama, bukan loop).
gniourf_gniourf
6
Saya pikir kamu salah. Ini adalah komentar wajib yang menyertai downvote, menjelaskan semua pola yang salah dan kesalahpahaman dari jawaban. Tolong, pelajari dari kesalahan Anda (dan sebelum itu, cobalah untuk memahaminya) daripada menjadi keras kepala. Menjadi orang baik juga tidak cocok dengan menyebarkan praktik buruk.
gniourf_gniourf
1
Atau, jika menggunakan Bash ≥4, Anda tidak perlu tr :if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf
5
Kode ini masih rusak parah. Itu masih menggunakan backticks alih-alih sintaks substitusi modern; masih memiliki kutipan yang tak tertandingi; masih memiliki tanda kutip yang hilang di tempat-tempat di mana mereka sebenarnya penting ; dll. Cobalah memasukkan beberapa karakter glob yang dikelilingi ruang kosong ke dalam data pengujian Anda, jika Anda tidak percaya bahwa kutipan yang hilang itu membuat perbedaan, dan perbaiki masalah shellcheck.net ditemukan hingga kode ini muncul bersih.
Charles Duffy
2
Adapun bahasa yang Anda kutip dari unix.stackexchange.com/questions/68694/… , yang Anda lewatkan adalah echo $foocontoh situasi di mana pengurai mengharapkan daftar kata-kata ; jadi di Anda echo ${F}, isi Fstring-split dan glob-diperluas. Hal yang sama berlaku untuk echo ${S:$N:1}contoh dan yang lainnya. Lihat BashPitfalls # 14 .
Charles Duffy