bash değişkeninde büyük harf ilk karakteri


Yanıtlar:


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

2
En iyi skorlu cevaptan daha karmaşık olmasına rağmen, bu aslında tam olarak bunu yapar: 'bir değişkende büyük harf ilk karakter'. En iyi skorlanan cevap bu sonuçlara sahip değildir. Basit cevaplar doğru cevaplardan daha istekli bir şekilde değerlendiriliyor gibi mi görünüyor?
Krzysztof Jabłoński

15
@ KrzysztofJabłoński: Aslında, aşağıdaki "en iyi skorlu cevap", Bash 4 altındaki bu cevapla aynı sonuçları verecektir. Bu cevap, bir alt kabuk (başka bir kabuk), ek yükü 'tr' (başka bir işlem) (Bash değil), burada-doc / string kullanmanın yükü (geçici dosya oluşturma) ve en iyi skorlanan cevaplayıcıya kıyasla iki ikame kullanır. Kesinlikle eski kod yazmanız gerekiyorsa, alt kabuk yerine bir işlev kullanmayı düşünün.
Steve

2
Bu cevap, girdinin küçük harf olduğunu varsayar. Bu varyantın hiçbir varsayımı yoktur: $ (tr '[: alt:]' '[: üst:]' <<< $ {foo: 0: 1}) $ (tr '[: üst:]' '[: alt: ] '<<< $ {foo: 1})
Itai Hanski

5
@ItaiHanski OP kalan karakterlere ne olması gerektiğini belirtmedi, sadece birincisi. Gerekiyordu onlar değiştirmek istedim notQuiteCameliçine NotQuiteCamel. Varyantınızın yan etkisi vardır veya kalanları küçük harflere zorlar - alt kabukların ve tr işlemlerinin sayısını iki katına çıkarmak.
Jesse Chisholm

3
@DanieleOrlando, true, ancak bu sorunun başka etiketi yok bash.
Charles Duffy

314

Bash ile tek yön (sürüm 4+):

foo=bar
echo "${foo^}"

baskılar:

Bar

2
Bunun tam tersi var mı?
CMCDragonkai

44
@CMCDragonkai: İlk harfi küçük harf yapmak için kullanın "${foo,}". Tüm harfleri küçük harf yapmak için tuşunu kullanın "${foo,,}". Tüm harfleri büyük harf yapmak için tuşunu kullanın "${foo^^}".
Steve

1
Kazara fark ${foo~}ve ${foo~~}aynı etkiye sahip ${foo^}ve ${foo^^}. Ama hiçbir yerde bahsettiğim alternatifi hiç görmedim.
mivk

5
Mac'lerde çalışmıyor gibi görünüyor. Aşağıdaki hatayı alıyorum:bad substitution
Toland Hon

1
@TolandHon: Muhtemelen daha önce de çalıştığınız için, 4.x sürümüne yükseltmeniz veya bu makine herhangi bir nedenle yükseltilemiyorsa başka bir çözüm denemeniz gerekir.
Steve

29

Şununla tek yön sed:

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

Baskılar:

Bar

10
MacOS10 Lion üzerinde çalışmaz sed, sigh, \ u bir operatör olmak yerine u olarak genişler.
vwvan

2
@vwvan yazın brew install coreutils gnu-sedve önek olmadan komutları kullanmak için talimatları izleyin g. Ne kadar değerli olursa olsun, GNU sürümlerini aldığından beri bu komutların OSX sürümünü asla çalıştırmak istemedim.
Dean

@vwvan: Evet, üzgünüm, sedbu durumda GNU'ya ihtiyacınız olacak
Steve

2
@Dean: FWIW, OSX'i çalıştırmak istemedim :-)
Steve

5
Sadece olarak değiştirin sed 's/./\U&/ve POSIX sed üzerinde çalışacaktır.
David Conrad

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

14

İşte "yerel" metin araçları yolu:

#!/bin/bash

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

nihayet bir değişken ve Mac üzerinde çalışan bir şey! Teşekkür ederim!
OZZIE

4
@DanieleOrlando, umabileceği kadar taşınabilir değil. veya aralıklarda tr [:lower:] [:upper:]olmayan harfleri içeren dil / yerel ayarlarda çalışması gerekiyorsa daha iyi bir seçimdir . a-zA-Z
Charles Duffy

8

Yalnızca awk kullanma

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

sonuç: Capcapizedizedstring
Alex Freshmann

4

Saf bash'da bash-3.2 ile de yapılabilir:

# 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}"

foo nasıl tanımlanır? Denedim foo = $1ama sadece -bash: foo: command not found
alıyorum

1
@ OZZIE, =ödevlerin etrafında boşluk yok . Bu, shellcheck.net'in sizin için programlama yoluyla bulacağı bir şeydir .
Charles Duffy

Kabuk komut dosyaları hakkında her zaman unutuyorum .. sadece bir boşluk (önce / sonra) önemli olan dil ... iç çekiş (doğru hatırlıyorsam python en az 4)
OZZIE

@OZZIE, önemli olmalı, çünkü önemli değilse =, bir programa argüman olarak geçemezdiniz ( someprogram =çalışıp çalışmadığını someprogramveya adlı bir değişkene atanıp atanmadığını nasıl bilebilir someprogram?)
Charles Duffy

3

Bu da işe yarıyor ...

FooBar=baz

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

=> Baz
FooBar=baz

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

=> bAz
FooBar=baz

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

=> baZ

Ve bunun gibi.

Kaynaklar:

Inroductions / Öğreticiler:


3

Yalnızca ilk kelimeyi büyük harf yapmak için:

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

O iki iki


Değişkendeki her kelimeyi büyük harf yapmak için:

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

O ne T wo T hree


(bash 4+ ile çalışır)


foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) Her sözcük için daha kısa çözünürlük. foo Şimdi "Bir İki Üç"
vr286

İlk 3 veya 4 harfi büyük harfe nasıl kullanabilirim? Gibi pqrs-123-v1 için PQSR-123-v1 ? Veya ilk kısa çizgi öncesi tüm harfler ...
Vicky Dev

2

Hem Linux hem de OSX için alternatif ve temiz çözüm, bash değişkenleriyle de kullanılabilir

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

Abc döndürür


0

Bu benim için çalıştı:

Geçerli dizindeki tüm * php dosyalarını arama ve her dosya adının ilk karakterini büyük harfe değiştirme:

örneğin: test.php => Test.php

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

4
Orijinal soru bir dize idi ve dosyaları yeniden adlandırmaya hiç başvurmadı.
AndySavage

0

sadece burada eğlenmek için:

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

Tam olarak ne istediğini değil, oldukça yararlı

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

foo=bar
echo $foo
BAR

Ve tam tersi

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
}

ilk harf-küçük-düşük-xc () {v-ilk harf-küçük | xclip -seçim panosu}


-7

İlk karakter bir harf değilse (sekme, boşluk ve çıkış karakterli çift tırnak) olursa ne olur ? Bir mektup bulana kadar test etsek iyi olur ! Yani:

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
Lütfen daha temiz bir kod yazın! her yerde alıntı yok . Eski sözdizimi (backticks) kullanıyorsunuz; antika sözdizimi ( $[...]) kullanıyorsunuz. Çok işe yaramaz parantez kullanıyorsunuz. Dizenin latin alfabesindeki karakterlerden oluştuğunu varsayıyorsunuz (aksanlı harfler veya diğer alfabe harfleri ne olacak?). Bu pasajı kullanılabilir hale getirmek için çok işin var! (ve normal ifadeyi kullandığınız için, döngü yerine ilk harfi bulmak için normal ifadeyi de kullanabilirsiniz).
gniourf_gniourf

6
Bence hatalısın. Yanıtın tüm yanlış kalıplarını ve yanılgılarını açıklayan, aşağı oyuna eşlik eden zorunlu yorum. Lütfen inatçı olmak yerine hatalarınızdan ders alın (ve ondan önce onları anlamaya çalışın). İyi bir arkadaş olmak da kötü uygulamaları yaymakla bağdaşmaz.
gniourf_gniourf

1
Veya, Bash ≥4 kullanıyorsanız, aşağıdakilere ihtiyacınız yoktur tr:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
9n17

5
Bu kod hala bozuk. Hala modern ikame sözdizimi yerine backticks kullanıyor; hala eşsiz tırnak işaretleri var; aslında önemli oldukları yerlerde hala eksik alıntılar var ; Bu eksik tırnakların bir fark yarattığına inanmıyorsanız ve bu kod temiz oluncaya kadar shellcheck.net'in bulduğu sorunları düzeltin .
Charles Duffy

2
Unix.stackexchange.com/questions/68694/… ' dan alıntıladığınız dile gelince , özlediğiniz şey ayrıştırıcının bir kelime listesi beklediği birecho $foo duruma örnektir ; böylece sizin içeriğiniz , string-split ve glob-expanded. Bu örnek ve diğerleri için de aynı şekilde geçerlidir . Bkz BashPitfalls # 14 . echo ${F}Fecho ${S:$N:1}
Charles Duffy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.