web-dev-qa-db-ja.com

Bashで文字列を小文字に変換する方法

bash に文字列を小文字の文字列に変換する方法はありますか?

たとえば、私が持っているなら:

a="Hi all"

私はそれをに変換したい:

"hi all"
1056
assassin

さまざまな方法があります。

POSIX標準

tr

$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all

_ awk _

$ echo "$a" | awk '{print tolower($0)}'
hi all

非POSIX

以下の例で移植性の問題に出くわすかもしれません:

Bash 4.0

$ echo "${a,,}"
hi all

sed

$ echo "$a" | sed -e 's/\(.*\)/\L\1/'
hi all
# this also works:
$ sed -e 's/\(.*\)/\L\1/' <<< "$a"
hi all

Perl

$ echo "$a" | Perl -ne 'print lc'
hi all

バッシュ

lc(){
    case "$1" in
        [A-Z])
        n=$(printf "%d" "'$1")
        n=$((n+32))
        printf \\$(printf "%o" "$n")
        ;;
        *)
        printf "%s" "$1"
        ;;
    esac
}
Word="I Love Bash"
for((i=0;i<${#Word};i++))
do
    ch="${Word:$i:1}"
    lc "$ch"
done
1779
ghostdog74

Bash 4では:

小文字に

$ string="A FEW WORDS"
$ echo "${string,}"
a FEW WORDS
$ echo "${string,,}"
a few words
$ echo "${string,,[AEIUO]}"
a FeW WoRDS

$ string="A Few Words"
$ declare -l string
$ string=$string; echo "$string"
a few words

大文字へ

$ string="a few words"
$ echo "${string^}"
A few words
$ echo "${string^^}"
A FEW WORDS
$ echo "${string^^[aeiou]}"
A fEw wOrds

$ string="A Few Words"
$ declare -u string
$ string=$string; echo "$string"
A FEW WORDS

切り替え(文書化されていませんが、コンパイル時にオプションで設定可能)

$ string="A Few Words"
$ echo "${string~~}"
a fEW wORDS
$ string="A FEW WORDS"
$ echo "${string~}"
a FEW WORDS
$ string="a few words"
$ echo "${string~}"
A few words

大文字にします(文書化されていませんが、コンパイル時にオプションで設定可能)

$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words

タイトルケース:

$ string="a few words"
$ string=($string)
$ string="${string[@]^}"
$ echo "$string"
A Few Words

$ declare -c string
$ string=(a few words)
$ echo "${string[@]}"
A Few Words

$ string="a FeW WOrdS"
$ string=${string,,}
$ string=${string~}
$ echo "$string"
A few words

declare属性を無効にするには、+を使用します。たとえば、declare +c stringです。これはその後の代入に影響し、現在の値には影響しません。

declareオプションは変数の属性を変更しますが、内容は変更しません。私の例の再割り当ては変更を示すために内容を更新します。

編集:

ghostdog74 で示唆されているように "Wordで最初の文字を切り替える"(${var~})を追加.

編集: / Bash 4.3と一致するようにチルダの動作を修正しました。

383
echo "Hi All" | tr "[:upper:]" "[:lower:]"
116
shuvalov

tr

a="$(tr [A-Z] [a-z] <<< "$a")"

_ awk _

{ print tolower($0) }

sed

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

私はこれが昔の投稿であることを知っていますが、私はそれをここに投稿することを考えていたので私は別のサイトのためにこの答えをしました:

UPPER - > lower : pythonを使う:

b=`echo "print '$a'.lower()" | python`

またはRuby:

b=`echo "print '$a'.downcase" | Ruby`

あるいはPerl(おそらく私のお気に入り):

b=`Perl -e "print lc('$a');"`

またはPHP:

b=`php -r "print strtolower('$a');"`

またはAwk:

b=`echo "$a" | awk '{ print tolower($1) }'`

それともSed:

b=`echo "$a" | sed 's/./\L&/g'`

またはバッシュ4:

b=${a,,}

NodeJSがあれば(そしてちょっとナッツですが…):

b=`echo "console.log('$a'.toLowerCase());" | node`

ddを使うこともできます(しかし私はしません!):

b=`echo "$a" | dd  conv=lcase 2> /dev/null`

下 - > UPPER

pythonを使う:

b=`echo "print '$a'.upper()" | python`

またはRuby:

b=`echo "print '$a'.upcase" | Ruby`

あるいはPerl(おそらく私のお気に入り):

b=`Perl -e "print uc('$a');"`

またはPHP:

b=`php -r "print strtoupper('$a');"`

またはAwk:

b=`echo "$a" | awk '{ print toupper($1) }'`

それともSed:

b=`echo "$a" | sed 's/./\U&/g'`

またはバッシュ4:

b=${a^^}

NodeJSがあれば(そしてちょっとナッツですが…):

b=`echo "console.log('$a'.toUpperCase());" | node`

ddを使うこともできます(しかし私はしません!):

b=`echo "$a" | dd  conv=ucase 2> /dev/null`

また、あなたが 'Shell'と言ったとき、私はあなたがbashを意味していると仮定しています、しかしあなたがzshを使うことができるなら、それは同じくらい簡単です

b=$a:l

小文字の場合

b=$a:u

大文字の場合.

38
nettux

Zshの場合:

echo $a:u

お奨めzsh!

26
Scott Smedley

GNU sedを使う:

sed 's/.*/\L&/'

例:

$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed 's/.*/\L&/')
$ echo "$foo"
some string
17
devnull

ビルトインだけを使った標準的なシェル(bashismなし)の場合

uppers=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lowers=abcdefghijklmnopqrstuvwxyz

lc(){ #usage: lc "SOME STRING" -> "some string"
    i=0
    while ([ $i -lt ${#1} ]) do
        CUR=${1:$i:1}
        case $uppers in
            *$CUR*)CUR=${uppers%$CUR*};OUTPUT="${OUTPUT}${lowers:${#CUR}:1}";;
            *)OUTPUT="${OUTPUT}$CUR";;
        esac
        i=$((i+1))
    done
    echo "${OUTPUT}"
}

そして大文字の場合:

uc(){ #usage: uc "some string" -> "SOME STRING"
    i=0
    while ([ $i -lt ${#1} ]) do
        CUR=${1:$i:1}
        case $lowers in
            *$CUR*)CUR=${lowers%$CUR*};OUTPUT="${OUTPUT}${uppers:${#CUR}:1}";;
            *)OUTPUT="${OUTPUT}$CUR";;
        esac
        i=$((i+1))
    done
    echo "${OUTPUT}"
}
11
technosaurus

プレバッシュ4.0

文字列の大文字小文字を区別せずに変数に代入する

VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]') 

echo "$VARIABLE"
10
hawkeye126

Bash 4ではtypesetを使うことができます

例:

A="HELLO WORLD"
typeset -l A=$A
8
c4f4t0r

正規表現

私が共有したいコマンドを信用したいのですが、真実は http://commandlinefu.com から私が使用するためにそれを得たということです。自分のホームフォルダ内の任意のディレクトリにcdすると、すべてのファイルおよびフォルダを小文字に再帰的に変更することになりますので注意してください。これは素晴らしいコマンドライン修正であり、ドライブに保存した多数のアルバムに特に役立ちます。

find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

現在のディレクトリまたはフルパスを示すfindの後に、ドット(。)の代わりにディレクトリを指定できます。

このコマンドがしないことが、スペースをアンダースコアに置き換えることが役に立つことを証明しています。

7
Derek Shaw

あなたはこれを試すことができます

s="Hello World!" 

echo $s  # Hello World!

a=${s,,}
echo $a  # hello world!

b=${s^^}
echo $b  # HELLO WORLD!

enter image description here

ref: http://wiki.workassis.com/Shell-script-convert-text-to-lowercase-and-uppercase/

6
Bikesh M Annur

この質問は何歳であり、 テクノサウルスによるこの回答 と似ていますが。ほとんどのプラットフォーム(That I Use)とbashの古いバージョンで移植可能なソリューションを見つけるのに苦労しました。また、配列、関数、および印刷、エコー、一時ファイルを使用して些細な変数を取得することにも不満を感じています。これは私にとってこれまでのところ非常にうまく機能し、私は共有すると思った。私の主なテスト環境は次のとおりです。

  1. GNU bash、バージョン4.1.2(1)-release(x86_64-redhat-linux-gnu)
  2. GNU bash、バージョン3.2.57(1)-release(sparc-Sun-solaris2.10)
lcs="abcdefghijklmnopqrstuvwxyz"
ucs="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
input="Change Me To All Capitals"
for (( i=0; i<"${#input}"; i++ )) ; do :
    for (( j=0; j<"${#lcs}"; j++ )) ; do :
        if [[ "${input:$i:1}" == "${lcs:$j:1}" ]] ; then
            input="${input/${input:$i:1}/${ucs:$j:1}}" 
        fi
    done
done

シンプル Cスタイルforループ 文字列を反復処理します。このようなものを見たことがない場合は、以下の行で これは私がこれを学んだ場所です 。この場合、行は入力にchar $ {input:$ i:1}(小文字)が存在するかどうかを確認し、存在する場合は指定されたchar $ {ucs:$ j:1}(大文字)に置き換えて保存します入力に戻ります。

input="${input/${input:$i:1}/${ucs:$j:1}}"
3
JaredTS486

4.0より前のBashバージョンでは、このバージョンが最も速いはずです( fork/exec anyコマンドではありません)。

function string.monolithic.tolower
{
   local __Word=$1
   local __len=${#__Word}
   local __char
   local __octal
   local __decimal
   local __result

   for (( i=0; i<__len; i++ ))
   do
      __char=${__Word:$i:1}
      case "$__char" in
         [A-Z] )
            printf -v __decimal '%d' "'$__char"
            printf -v __octal '%03o' $(( $__decimal ^ 0x20 ))
            printf -v __char \\$__octal
            ;;
      esac
      __result+="$__char"
   done
   REPLY="$__result"
}

technosaurus's answer それは可能性を秘めていたが、それは私にとってはうまくいった。

3
Orwellophile

V4を使用している場合、これは baked-in です。そうでなければ、これは 単純で広く適用可能な の解決策です。このスレッドに関する他の回答(およびコメント)は、以下のコードを作成するのに非常に役立ちました。

# Like echo, but converts to lowercase
echolcase () {
    tr [:upper:] [:lower:] <<< "${*}"
}

# Takes one arg by reference (var name) and makes it lowercase
lcase () { 
    eval "${1}"=\'$(echo ${!1//\'/"'\''"} | tr [:upper:] [:lower:] )\'
}

ノート:

  • a="Hi All"を実行してから:lcase aを実行すると、次のようになります。a=$( echolcase "Hi All" )
  • Lcase関数では、${!1//\'/"'\''"}の代わりに${!1}を使用すると、文字列に引用符が含まれている場合でもこれを機能させることができます。
3

Bashを実際には使用していない、外部プログラムを使用した多くの答え。

Bash4が利用可能になることをご存知の場合は、実際には${VAR,,}表記を使用する必要があります(簡単でかっこいいです)。 4より前のBashの場合(私のMacはまだBash 3.2を使用しています)。より移植性の高いバージョンを作成するために、@ ghostdog74の修正版を使用しました。

lowercase 'my STRING'を呼び出して小文字のバージョンを取得することができます。結果をvarに設定することについてのコメントを読みましたが、文字列を返すことはできないので、これはBashに移植することはできません。それを印刷することが最善の解決策です。 var="$(lowercase $str)"のようなもので簡単にキャプチャできます。 

これがどのように機能するか

これが機能する方法は、各文字のASCII整数表現をprintfで、次にadding 32の場合はupper-to->lowerを、またはsubtracting 32の場合はlower-to->upperを取得することです。それから、printfをもう一度使って数値をcharに変換します。 'A' -to-> 'a'から32文字の違いがあります。

説明するのにprintfを使う:

$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65

97 - 65 = 32

そしてこれは例を含む作業バージョンです。
コード内のコメントはたくさんのことを説明しているので注意してください。

#!/bin/bash

# lowerupper.sh

# Prints the lowercase version of a char
lowercaseChar(){
    case "$1" in
        [A-Z])
            n=$(printf "%d" "'$1")
            n=$((n+32))
            printf \\$(printf "%o" "$n")
            ;;
        *)
            printf "%s" "$1"
            ;;
    esac
}

# Prints the lowercase version of a sequence of strings
lowercase() {
    Word="$@"
    for((i=0;i<${#Word};i++)); do
        ch="${Word:$i:1}"
        lowercaseChar "$ch"
    done
}

# Prints the uppercase version of a char
uppercaseChar(){
    case "$1" in
        [a-z])
            n=$(printf "%d" "'$1")
            n=$((n-32))
            printf \\$(printf "%o" "$n")
            ;;
        *)
            printf "%s" "$1"
            ;;
    esac
}

# Prints the uppercase version of a sequence of strings
uppercase() {
    Word="$@"
    for((i=0;i<${#Word};i++)); do
        ch="${Word:$i:1}"
        uppercaseChar "$ch"
    done
}

# The functions will not add a new line, so use echo or
# append it if you want a new line after printing

# Printing stuff directly
lowercase "I AM the Walrus!"$'\n'
uppercase "I AM the Walrus!"$'\n'

echo "----------"

# Printing a var
str="A StRing WITH mixed sTUFF!"
lowercase "$str"$'\n'
uppercase "$str"$'\n'

echo "----------"

# Not quoting the var should also work, 
# since we use "$@" inside the functions
lowercase $str$'\n'
uppercase $str$'\n'

echo "----------"

# Assigning to a var
myLowerVar="$(lowercase $str)"
myUpperVar="$(uppercase $str)"
echo "myLowerVar: $myLowerVar"
echo "myUpperVar: $myUpperVar"

echo "----------"

# You can even do stuff like
if [[ 'option 2' = "$(lowercase 'OPTION 2')" ]]; then
    echo "Fine! All the same!"
else
    echo "Ops! Not the same!"
fi

exit 0

そしてこれを実行した後の結果:

$ ./lowerupper.sh 
i am the walrus!
I AM THE WALRUS!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
myLowerVar: a string with mixed stuff!
myUpperVar: A STRING WITH MIXED STUFF!
----------
Fine! All the same!

これはASCII文字に対してのみ機能するはずです /。 

私にはASCII文字だけを渡すことがわかっているので、それは問題ありません。
たとえば、大文字と小文字を区別しないCLIオプションとしてこれを使用しています。

3
Gus Neves

あなたがpythonが好きで新しいpythonパッケージをインストールするオプションがあるなら、 pythonユーティリティ を試すことができます。

# install pythonp
$ pip install pythonp

$ echo $a | pythonp "l.lower()"
2
bombs

大文字と小文字の変換はアルファベットでのみ行われます。だから、これはうまく機能するはずです。

アルファベットを大文字から小文字に変換することに焦点を当てています。他の文字はそのまま標準出力に表示されるべきです。

パス/ to/file/filename内のすべてのテキストをAからZの範囲内でAからZに変換します。

小文字から大文字への変換用

cat path/to/file/filename | tr 'a-z' 'A-Z'

大文字から小文字への変換用

cat path/to/file/filename | tr 'A-Z' 'a-z'

例えば、

ファイル名:

my name is xyz

に変換されます:

MY NAME IS XYZ

例2

echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK

例3

echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
1
theBuzzyCoder

変換した文字列を変数に格納します。以下は私のために働きました - $SOURCE_NAMEから$TARGET_NAME 

TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"
0
nitinr708

これは JaredTS486のアプローチ のはるかに速いバリエーションで、ネイティブのBash機能(Bashバージョン<4.0を含む)を使用して彼のアプローチを最適化します。

小文字と大文字の両方の変換で、小さい文字列(25文字)と大きい文字列(445文字)に対して1000回この方法を繰り返しました。テスト文字列は主に小文字なので、小文字への変換は通常大文字よりも高速です。

私のアプローチと、このページにあるBash 3.2と互換性のある他のいくつかの答えを比較しました。私のアプローチはここで文書化されているほとんどのアプローチよりはるかに高性能であり、いくつかのケースではtrよりもさらに高速です。

これは、25文字の1,000回の反復のタイミング結果です。

445文字(Witter Bynnerによる "The Robin"の詩からなる)の1000回の繰り返しのタイミング結果:

  • 私の小文字へのアプローチは2秒です。大文字の12秒
  • trの場合は4が小文字になります。大文字の4秒
  • Orwellophileのアプローチ は小文字の20秒。大文字の29秒
  • ghostdog74's の場合は75秒。大文字の場合は669です。大部分が一致するテストと大部分が失敗するテストの間でパフォーマンスの違いがどれほど劇的に異なるかに注目することは興味深いです。
  • technosaurus 'approach には467秒。大文字の449
  • JaredTS486のアプローチ の場合は660秒。大文字は660秒です。興味深いことに、この方法ではBashで連続的なページフォルト(メモリスワッピング)が発生しました。

溶液:

#!/bin/bash
set -e
set -u

declare LCS="abcdefghijklmnopqrstuvwxyz"
declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"

function lcase()
{
  local TARGET="${1-}"
  local UCHAR=''
  local UOFFSET=''

  while [[ "${TARGET}" =~ ([A-Z]) ]]
  do
    UCHAR="${BASH_REMATCH[1]}"
    UOFFSET="${UCS%%${UCHAR}*}"
    TARGET="${TARGET//${UCHAR}/${LCS:${#UOFFSET}:1}}"
  done

  echo -n "${TARGET}"
}

function ucase()
{
  local TARGET="${1-}"
  local LCHAR=''
  local LOFFSET=''

  while [[ "${TARGET}" =~ ([a-z]) ]]
  do
    LCHAR="${BASH_REMATCH[1]}"
    LOFFSET="${LCS%%${LCHAR}*}"
    TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}"
  done

  echo -n "${TARGET}"
}

そのアプローチは簡単です:入力文字列に残っている大文字が残っている間に、次のものを見つけ、その小文字のすべてのインスタンスをその小文字のバリエーションで置き換えます。すべての大文字が置き換えられるまで繰り返します。

私のソリューションのいくつかのパフォーマンス特性

  1. 新しいプロセスで外部バイナリユーティリティを呼び出すことによるオーバーヘッドを回避する、シェル組み込みユーティリティのみを使用します。
  2. パフォーマンスの低下を招くサブシェルを回避します。
  3. 変数内でのグローバル文字列の置換、変数接尾辞のトリミング、正規表現の検索とマッチングなど、コンパイルされパフォーマンスが最適化されたシェルメカニズムを使用します。これらのメカニズムは、文字列を手動で繰り返すよりはるかに高速です。
  4. 変換される一意の一致文字の数に必要な回数だけループします。たとえば、3つの異なる大文字を含む文字列を小文字に変換するのに必要なのは、3回のループ反復だけです。事前設定されたASCIIアルファベットの場合、ループ反復の最大数は26です。
  5. UCSLCSは追加の文字で補強することができます
0
Dejay Clayton