Bash에서 문자열을 소문자로 변환하는 방법은 무엇입니까?


답변:


2180

다양한 방법이 있습니다 :

POSIX 표준

tr

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

AWK

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

비 POSIX

다음 예제에서 이식성 문제가 발생할 수 있습니다.

배쉬 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

$ 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

참고 : 이것에 대한 YMMV. 를 사용하더라도 (GNU bash 버전 4.2.46 및 4.0.33 (및 동일한 동작 2.05b.0이지만 대소 문자 일치는 구현되지 않음)) 작동하지 않습니다 shopt -u nocasematch;. nocasematch를 설정하지 않으면 [[ "fooBaR"== "FOObar"]]가 OK BUT과 일치하지만 이상하게도 [bz]가 [AZ]와 잘못 일치합니다. 배쉬는 이중 부정 ( "unset nocasematch")에 의해 혼동된다! :-)


9
내가 뭔가를 놓치고 있습니까, 아니면 마지막 예 (Bash)가 실제로 완전히 다른 것을합니까? 그것은 "ABX"에 대한 작동하지만, 대신 할 경우 word="Hi All"다른 예제처럼, 그것은 반환 ha하지 hi all. 대문자로만 작동하며 이미 소문자로 된 문자는 건너 뜁니다.
jangosteve

26
POSIX 표준 에는 trawk예제 만 지정되어 있습니다.
Richard Hansen

178
tr '[:upper:]' '[:lower:]'현재 로케일을 사용하여 대문자 / 소문자 등가를 판별하므로 분음 부호가있는 문자를 사용하는 로케일에서 작동합니다.
Richard Hansen

10
출력을 새로운 변수로 가져 오는 방법은 무엇입니까? 즉, 소문자 문자열을 새로운 변수로 만들고 싶다고 말합니까?
Adam Parkin

60
@ 아담 :b="$(echo $a | tr '[A-Z]' '[a-z]')"
티노

434

배쉬 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에서${var~} 제안한대로 "첫 문자를 단어별로 전환"( )을 추가했습니다 .

편집 : Bash 4.3과 일치하도록 물결표 동작이 수정되었습니다.


5
"^"및 ","연산자는 ASCII가 아닌 문자에 대해서는 작동하지 않지만 "~~"는 작동 string="łódź"; echo ${string~~}하지만 echo ${string^^}"ŁÓDŹ"는 반환 하지만 "łóDź"는 반환합니다. 에서도 LC_ALL=pl_PL.utf-8. bash 4.2.24를 사용하고 있습니다.
Hubert Kario

2
@HubertKario : 이상합니다. Bash 4.0.33에서도 동일한 문자열을 사용하여 동일합니다 en_US.UTF-8. 버그이며 신고했습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

1
@HubertKario : 사용해보십시오 echo "$string" | tr '[:lower:]' '[:upper:]'. 아마도 같은 실패를 보일 것입니다. 따라서 문제는 적어도 부분적으로 Bash가 아닙니다.
추후 공지가있을 때까지 일시 중지되었습니다.

1
@ DennisWilliamson : 예, 나도 그것을 알아 냈습니다 (Suvalov의 답변에 대한 의견 참조). "이것은 ASCII만을위한 것"이라고 말하고 싶지만 작동하는 "~~"연산자이기 때문에 코드와 번역 테이블이없는 것 같습니다 ...
Hubert Kario

4
@ HubertKario : Bash 관리자는 버그 를 인정 하고 다음 릴리스에서 수정 될 것이라고 말했습니다.
추후 공지가있을 때까지 일시 중지되었습니다.

123
echo "Hi All" | tr "[:upper:]" "[:lower:]"

4
@RichardHansen : ACII tr이외의 문자에는 작동하지 않습니다. 올바른 로케일 세트와 로케일 파일이 생성되었습니다. 내가 뭘 잘못하고 있는지 알 수 있습니까?
Hubert Kario

참고 : 이것은 Windows / Msys에서 작동했습니다. 다른 제안 중 일부는 그렇지 않았습니다.
wasatchwizard

3
[:upper:]필요한가요?
mgutt

77

tr :

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

AWK :

{ print tolower($0) }

sed :

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

2
+1 a="$(tr [A-Z] [a-z] <<< "$a")"이 가장 쉬워 보입니다. 나는 ... 아직 초보
Sandeepan 나스

2
sed해결책을 강력히 추천합니다 . 나는 어떤 이유로없는 환경에서 일하고 tr있지만 아직없는 시스템을 찾지 못했습니다 sed. 더 많은 시간을 보내고 싶습니다. sed어쨌든 다른 일을 했으므로 체인을 만들 수 있습니다. 명령을 하나의 긴 문으로 묶습니다.
Haravikk 2009 년

2
괄호 표현식은 인용해야합니다. 에서 tr [A-Z] [a-z] A단일 문자로 구성된 파일 이름이 있거나 nullgob 이 설정된 경우 셸에서 파일 이름 확장을 수행 할 수 있습니다 . tr "[A-Z]" "[a-z]" A제대로 작동합니다.
Dennis

2
@CamiloMartin 그것은 특히 Synology NAS와 같은 문제가있는 BusyBox 시스템이지만 다른 시스템에서도 발생했습니다. 나는 최근에 많은 크로스 플랫폼 쉘 스크립팅을 해왔으며 추가로 설치할 필요가 없기 때문에 매우 까다로워집니다! 그러나 아직 시스템이없는 시스템에 직면했습니다sed
Haravikk

2
참고 tr [A-Z] [a-z]거의 모든 로케일에서 올바르지 않습니다. 예를 들어 en-US로케일에서 A-Z실제로 interval AaBbCcDdEeFfGgHh...XxYyZ입니다.
fuz

44

나는 이것이 오래된 게시물이라는 것을 알고 있지만 다른 사이트에 대해이 답변을 만들었으므로 여기에 게시 할 것이라고 생각했습니다.

상단-> 하단 : 파이썬 사용 :

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

또는 루비 :

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`

하한-> 상한 :

파이썬을 사용하십시오 :

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

또는 루비 :

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

대문자.


@JESii 모두 위-> 아래 및 아래-> 위를 위해 작동합니다. 64 비트 데비안 스트레치에서 sed 4.2.2 및 Bash 4.3.42 (1)을 사용하고 있습니다.
nettux

1
안녕하세요, @ nettux443 ... 방금 bash 작업을 다시 시도했는데 "나쁜 대체"오류 메시지가 표시되어 여전히 실패합니다. 저는 homebrew의 bash를 사용하여 OSX를 사용하고 있습니다 : GNU bash, 버전 4.3.42 (1)-릴리스 (x86_64-apple-darwin14.5.0)
JESii

5
사용하지 마세요! 스크립트를 생성하는 모든 예제는 매우 취약합니다. 값에 a작은 따옴표 가 포함 된 경우 동작이 깨졌을뿐 아니라 심각한 보안 문제가 발생한 것입니다.
tripleee

sed는 항상 어디에나 있기 때문에 sed 솔루션을 가장 좋아합니다.
Dudi Boy

dd 솔루션을 선호합니다. 작동하려면 루트가되어야합니다.
inetphantom


18

GNU 사용 sed:

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

예:

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

12

프리 배쉬 4.0

Bash 문자열의 대소 문자를 낮추고 변수에 할당

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

echo "$VARIABLE"

5
echo파이프 필요 없음 : 사용$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Tino

3
@Tino here 문자열은 이전 버전의 Bash로 다시 이식 할 수 없습니다. 나는 그것이 v3에 도입되었다고 생각합니다.
tripleee

1
@tripleee 당신이 맞습니다, 그것은 bash-2.05b에서 소개되었습니다 – 그러나 그것은 제가 시스템에서 찾을 수있는 가장 오래된 bash입니다
Tino

11

내장 만 사용하는 표준 쉘 (bashisms 없음)의 경우 :

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

FreeBSD에서 이식성이 없어서이 스크립트에서 bashism을하지 않았는지 궁금합니다 : $ {1 : $ ...} : 나쁜 대체
Dereckson

2
과연; 하위 문자열 ${var:1:1}은 Bashism입니다.
tripleee

이 접근 방식에는 성능 메트릭이 매우 나쁩니다. 메트릭에 대한 내 답변을 참조하십시오.
Dejay Clayton

9

bash 4에서는 typeset을 사용할 수 있습니다

예:

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


7

정규식

공유하고 싶은 명령에 대해 신용을 얻고 싶지만 사실은 http://commandlinefu.com 에서 본인이 사용하기 위해 얻은 것입니다 . 그것은 장점을 가지고 당신의 경우 cd는 재귀를 소문자주의하여 사용하시기 바랍니다 모든 파일과 폴더를 변경할 것입니다 자신의 홈 폴더 내의 디렉토리로 이동합니다. 그것은 훌륭한 명령 줄 수정이며 특히 드라이브에 저장된 여러 앨범에 유용합니다.

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

find 다음에 현재 디렉토리 또는 전체 경로를 나타내는 dot (.) 대신 디렉토리를 지정할 수 있습니다.

이 솔루션 이이 명령이 수행하지 않는 한 가지 유용한 방법은 공백을 밑줄로 바꾸는 것입니다.


이것은 괜찮아 보이지만 어떤 이유로 든 나를 위해 작동하지 않았습니다. 나는 이것을 대안으로 작동하게했다 : find. -exec / bin / bash -c 'mv {}`tr [AZ] [az] <<< {}`'\;
John Rix

이것은 필요 prename에서 perl: dpkg -S "$(readlink -e /usr/bin/rename)"제공perl: /usr/bin/prename
티노

4

실제로 사용하지 않는 외부 프로그램을 사용하는 많은 답변 Bash.

Bash4를 사용할 수 있다는 것을 알고 있다면 실제로 ${VAR,,}표기법을 사용해야합니다 (쉽고 시원합니다). Bash before 4 이전의 경우 (My Mac은 여전히 ​​Bash 3.2를 사용합니다). 더 나은 버전을 만들기 위해 수정 된 @ ghostdog74 답변 버전을 사용했습니다.

하나는 당신이 전화를 lowercase 'my STRING'하고 소문자 버전을 얻을 수 있습니다 . 결과를 var로 설정하는 것에 대한 의견을 읽었지만 Bash문자열을 반환 할 수 없으므로 실제로 이식 할 수는 없습니다. 인쇄하는 것이 가장 좋습니다. 같은 것으로 쉽게 캡처 할 수 var="$(lowercase $str)"있습니다.

작동 원리

이것이 작동하는 방식은 각 문자의 ASCII 정수 표현 printfadding 32if 와 if upper-to->lower또는 subtracting 32if 로 얻는 것 lower-to->upper입니다. 그런 다음 printf다시 사용 하여 숫자를 다시 문자로 변환하십시오. 에서 '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 옵션에 이것을 사용하고 있습니다.


4

대소 문자 변환은 알파벳에 대해서만 수행됩니다. 따라서 이것은 깔끔하게 작동해야합니다.

az 사이의 알파벳을 대문자에서 소문자로 변환하는 데 중점을 둡니다. 다른 문자는 그대로 stdout으로 인쇄해야합니다 ...

az 범위 내의 path / to / file / filename에있는 모든 텍스트를 AZ로 변환

소문자를 대문자로 변환

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

3

v4를 사용하는 경우 구운 것입니다 . 그렇지 않은 경우 여기에 간단하고 광범위하게 적용 가능한 솔루션이 있습니다. 이 스레드에 대한 다른 답변 (및 의견)은 아래 코드를 만드는 데 매우 도움이되었습니다.

# 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

4.0 이전의 Bash 버전의 경우이 버전이 가장 빠릅니다 ( 명령을 포크 / 실행 하지 않으므로 ).

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의 대답 은 잠재력이 있었지만 나에게 제대로 실행되었습니다.


나쁘지 않다! 이 방법의 성능을 분석하려면 메트릭에 대한 내 답변을 참조하십시오.
Dejay Clayton

3

이 질문은 몇 살이었지만 technosaurus의 답변 과 비슷합니다 . 구식 버전의 bash뿐만 아니라 대부분의 플랫폼 (이것은 내가 사용하는)에서 이식 가능한 솔루션을 찾는 데 어려움을 겪었습니다. 또한 배열, 함수 및 인쇄, 반향 및 임시 파일을 사용하여 사소한 변수를 검색하는 데 좌절했습니다. 이것은 내가 공유 할 것이라고 생각한 지금까지 매우 잘 작동합니다. 내 주요 테스트 환경은 다음과 같습니다.

  1. GNU bash, 버전 4.1.2 (1)-릴리스 (x86_64-redhat-linux-gnu)
  2. GNU bash, 버전 3.2.57 (1)-릴리스 (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}}"

이것은 위의 예에서 650 번 반복되며 내 컴퓨터에서 1000 번의 호출을 실행하는 데 35 초가 걸립니다. 1000 회 호출을 실행하는 데 11 회만 반복되고 5 초 미만이 걸리는 대안에 대해서는 내 대안 답변을 참조하십시오.
Dejay Clayton

1
고맙지 만, 그것은 그것을 보는 것에서 분명해야합니다. 아마도 페이지 결함은 입력 크기와 반복 횟수에서 비롯된 것일 수 있습니다. 그럼에도 불구하고 나는 당신의 해결책을 좋아합니다.
JaredTS486

3

이는 기본 Bash 기능 (Bash 버전 <4.0 포함)을 사용하여 자신의 접근 방식을 최적화하는 JaredTS486 접근 방식의 훨씬 빠른 변형입니다 .

소문자와 대문자 변환 모두에서 작은 문자열 (25 자)과 큰 문자열 (445 자)에 대해이 방법을 1,000 회 반복했습니다. 테스트 문자열은 주로 소문자이므로 소문자로의 변환은 일반적으로 대문자보다 빠릅니다.

이 페이지에서 Bash 3.2와 호환되는 다른 답변과 내 접근 방식을 비교했습니다. 내 접근 방식은 여기에 설명 된 대부분의 접근 방식보다 훨씬 성능이 뛰어나며 tr여러 경우 보다 훨씬 빠릅니다 .

다음은 25 개의 문자를 1,000 회 반복 한 타이밍 결과입니다.

445 자 (1000 번 반복)의 타이밍 결과 (Witter Bynner의 "The Robin"시 구성) :

  • 내 소문자 접근 방식의 경우 2 초; 대문자 12 초
  • tr소문자를 위한 4s ; 대문자의 경우 4 초
  • Orwellophile의 소문자 접근 방식 은 20 ; 대문자 29
  • ghostdog74의 소문자 접근 방식은 75입니다 . 대문자의 경우 669 초. 우세한 경기와 우세한 경기의 시험 사이의 성능 차이가 얼마나 극적인지 주목하는 것은 흥미 롭습니다.
  • technosaurus의 소문자 접근 방식 에 대한 467 ; 대문자 449s
  • 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추가 문자로 확장 될 수 있습니다

2

변환 된 문자열을 변수에 저장합니다. 나를 위해 일한 다음 - $SOURCE_NAME$TARGET_NAME

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

1

간단한 방법

echo "Hi all" | awk '{ print tolower($0); }'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.