bashで変数の最初の文字を大文字にする


回答:


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

2
最高得点の回答よりも複雑ですが、これは実際には「変数の最初の文字を大文字にする」ということとまったく同じです。最高得点の回答にはその結果はありません。単純な答えは正しい答えよりも積極的に賛成されているように見えますか?
KrzysztofJabłoński2016

15
@KrzysztofJabłoński:実際、以下の「最高得点の回答」は、Bash 4でのこの回答と同じ結果になります。この回答には、サブシェル(別のシェル)を呼び出すオーバーヘッドと、「tr」ユーティリティ(別のプロセス)を呼び出すオーバーヘッドがあります、Bashではありません)、here-doc / string(一時ファイルの作成)を使用した場合のオーバーヘッドであり、最高スコアの回答と比較して2つの置換を使用します。レガシーコードを絶対に書く必要がある場合は、サブシェルの代わりに関数を使用することを検討してください。
スティーブは

2
この回答は、入力がすべて小文字であることを前提としています。このバリアントには仮定がありません:$(tr '[:lower:]' '[:upper:]' <<< $ {foo:0:1})$(tr '[:upper:]' '[:lower: ] '<<< $ {foo:1})
Itai Hanski

5
@ItaiHanski OPは、残りの文字に何が起こるかを指定しませんでした。最初の文字のみです。に変更notQuiteCamelしたいとしNotQuiteCamelます。バリアントには副作用があり、残りを小文字にする必要があります-サブシェルとtrプロセスの数を2倍にすることを犠牲にして。
ジェシーチザム2016

3
@DanieleOrlando、本当ですが、この質問には以外のタグはありませんbash
Charles Duffy 2017年

313

bashによる1つの方法(バージョン4+):

foo=bar
echo "${foo^}"

プリント:

Bar

2
これの反対はありますか?
CMCDragonkai 2015

44
@CMCDragonkai:最初の文字を小文字にするには、を使用します"${foo,}"。すべての文字を小文字にするには、を使用します"${foo,,}"。すべての文字を大文字にするには、を使用します"${foo^^}"
Steve

1
誤ってそれに気づき、${foo~}およびと${foo~~}同じ効果が ${foo^}あり${foo^^}ます。しかし、その代替案がどこかで言及されたことはありませんでした。
mivk

5
これはMacでは動作しないようです。次のエラーが表示されます:bad substitution
Toland Hon

1
@TolandHon:おそらくすでに問題を解決しているので、バージョン4.xにアップグレードするか、何らかの理由でそのマシンをアップグレードできない場合は別の解決策を試す必要があります。
スティーブ

29

片道sed

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

プリント:

Bar

10
MacOS10で動作しないLion sed、sigh、\ uは、オペレーターではなくuに展開されます。
vwvan 2014年

2
@vwvan brew install coreutils gnu-sedの指示に従い、接頭辞なしのコマンドを使用しますg。GNUバージョンを取得して以来、これらのコマンドのOSXバージョンを実行したくありませんでした。
ディーン

@vwvan:はい、申し訳ありませんが、sedこの場合はGNUが必要になります
Steve

2
@Dean:FWIW、私はOSXを実行したくなかった:-)
Steve

5
変更するだけでsed 's/./\U&/、POSIX sedで動作します。
デビッドコンラッド


14

これが「ネイティブ」テキストツールの方法です。

#!/bin/bash

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

最後に、変数とMacで動作するもの!ありがとうございました!
OZZIE 2017年

4
@DanieleOrlando、希望するほどポータブルではありません。または範囲外のtr [:lower:] [:upper:]文字を組み込んだ言語/ロケールで動作する必要がある場合は、より良い選択です。a-zA-Z
Charles Duffy

8

awkのみを使用する

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

結果:Uncapitalizedstring
Alex Freshmann

4

これは、bash-3.2を使用した純粋なbashでも実行できます。

# 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の定義方法は?試してみたfoo = $1が、しか得られなかった-bash: foo: command not found
OZZIE 2017年

1
@OZZIE、=割り当て内のスペースなし。これは、shellcheck.netがプログラムで見つけるものです。
Charles Duffy

私は常にシェルスクリプトについてそれを忘れます.. 1つのスペース(前/後)が重要な言語のみ...ため息(私が正しく覚えている場合、Pythonは少なくとも4です)
OZZIE

@OZZIE、それ重要である、なぜならそれが重要でないなら、あなたは=プログラムへの引数として渡すことができなかったからですsomeprogram =(実行されているかどうかsomeprogram、または名前が付けられた変数に割り当てるかどうかを知るにはどうすればよいsomeprogramですか)
Charles Duffy

3

これも動作します...

FooBar=baz

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

=> Baz
FooBar=baz

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

=> bAz
FooBar=baz

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

=> baZ

等々。

出典:

はじめに/チュートリアル:


3

最初の単語のみを大文字にするには:

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

Oの NE 2 3


変数内のすべての単語を大文字にするには:

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

O NE T WO Tの HREE


(bash 4+で動作)


foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) すべての単語の短い解決。foo Now is "One Two Three"
vr286 '16

2

LinuxとOSXの両方の代替のクリーンソリューションで、bash変数でも使用できます

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

Abcを返します


0

これは私のために働きました:

現在のディレクトリですべての* phpファイルを検索し、各ファイル名の最初の文字を大文字に置き換えます。

例:test.php => Test.php

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

4
元の質問は文字列であり、ファイル名の変更については言及していませんでした。
AndySavage 2017

0

ちょうど楽しみのためにここにいます:

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

正確には尋ねられたものではないが、非常に役立つ

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

foo=bar
echo $foo
BAR

そしてその逆

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-letter-to-lower-xc(){v-first-letter-to-lower | xclip -selectionクリップボード}


-7

最初の文字文字ではない(タブ、スペース、エスケープされた二重引用符である)場合はどうなりますか?手紙が見つかるまでテストした方がいいです。そう:

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
よりクリーンなコードを書いてください!あちこちで引用符が不足しています廃止された構文(バッククォート)を使用しています。時代遅れの構文($[...])を使用しています。無駄な括弧をたくさん使っています。文字列がラテンアルファベットの文字で構成されていると想定しています(アクセント付きの文字、または他のアルファベットの文字はどうですか)。このスニペットを使用可能にするために多大な労力を費やしています!(そして、正規表現を使用しているので、ループの代わりに正規表現を使用して最初の文字を見つけることもできます)。
gniourf_gniourf 2017年

6
私はあなたが間違っていると思います。反対票に付随する義務的なコメントは、回答のすべての誤ったパターンと誤解を説明しています。頑固なことをする代わりに、あなたの過ちから学びなさい(そしてその前に、それらを理解しようと努めなさい)。良き仲間であることは、悪い習慣を広めることとも両立しません。
gniourf_gniourf 2017年

1
または、バッシュ≥4を使用している場合、あなたは必要ありませんtrif [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf

5
このコードはまだひどく壊れています。最新の置換構文ではなく、まだバックティックを使用しています。それはまだ比類のない引用符を持っています。実際に重要な場所で引用符が欠けています。空白引用符の欠落が違いを生むと思わない場合は、空白で囲まれたグロブ文字をテストデータに入れて、このコードがクリーンになるまでshellcheck.netが検出する問題を修正してください
Charles Duffy 2017年

2
あなたがから引用した言語についてはunix.stackexchange.com/questions/68694/...、何を逃すことはつまりecho $foo、状況の一例であるパーサが単語のリストを期待します。したがってecho ${F}、のコンテンツFは文字列分割され、グロブ展開されます。これは、このecho ${S:$N:1}例と残りのすべてについても同様です。BashPitfalls#14を参照してください。
Charles Duffy 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.