题 如何在Bash中将字符串转换为小写?


有办法吗?  将字符串转换为小写字符串?

例如,如果我有:

a="Hi all"

我想将其转换为:

"hi all"

917
2018-02-15 07:02


起源


也可以看看: stackoverflow.com/questions/11392189 - dreftymac


答案:


各种方式:

TR

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

AWK

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

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

1589
2018-02-15 07:43



我错过了什么,或者你的最后一个例子(在Bash中)是否真的做了一些完全不同的事情?它适用于“ABX”,但如果您改为“ABX” word="Hi All" 像其他例子一样,它返回 ha不是 hi all。它仅适用于大写字母并跳过已经较低的字母。 - jangosteve
请注意,只有 tr 和 awk 示例在POSIX标准中指定。 - Richard Hansen
tr '[:upper:]' '[:lower:]' 将使用当前区域设置来确定大写/小写等效项,因此它将适用于使用带变音符号的字母的区域设置。 - Richard Hansen
如何将输出转换为新变量?即我想将小写字符串转换为新变量? - Adam Parkin
@亚当: b="$(echo $a | tr '[A-Z]' '[a-z]')" - Tino


在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 options更改变量的属性,但不更改内容。我的示例中的重新分配更新了内容以显示更改。

编辑:

添加了“逐字切换”(${var~})按照建议 ghostdog74

编辑: 修正了与Bash 4.3匹配的波形符。


350
2018-02-15 10:31



还有 ${string~} - ghostdog74
相当古怪,“^^”和“,,”运算符不适用于非ASCII字符,但“~~”确实... string="łódź"; echo ${string~~} 将返回“ŁÓDŹ”,但是 echo ${string^^} 返回“łóDź”。即使在 LC_ALL=pl_PL.utf-8。那是使用bash 4.2.24。 - Hubert Kario
@HubertKario:这很奇怪。对于我来说,在Bash 4.0.33中使用相同的字符串也是一样的 en_US.UTF-8。这是一个错误,我已经报告过了。 - Dennis Williamson
@HubertKario:试试 echo "$string" | tr '[:lower:]' '[:upper:]'。它可能会表现出同样的失败。所以问题至少部分不是Bash的问题。 - Dennis Williamson
@HubertKario:Bash维护者有 承认 该错误并声明它将在下一个版本中修复。 - Dennis Williamson


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

108
2018-02-15 07:13



+1不假设英语 - Richard Hansen
@RichardHansen: tr 对于非ACII字符不起作用。我确实有正确的语言环境集和生成的语言环境文件。知道我能做错什么吗? - Hubert Kario
仅供参考:这适用于Windows / Msys。其他一些建议没有。 - wasatchwizard


TR

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

AWK

{ print tolower($0) }

SED

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

70
2018-02-15 07:03



+1 a="$(tr [A-Z] [a-z] <<< "$a")" 看起来对我来说最容易。我还是初学者...... - Sandeepan Nath
我强烈推荐 sed 解;我一直在一个由于某种原因没有的环境中工作 tr 但我还没有找到一个系统 sed,加上我想做的很多时间,我刚做了其他的事情 sed 无论如何,所以可以将命令链接在一起(单个)长语句。 - Haravikk
应引用括号表达式。在 tr [A-Z] [a-z] A如果文件名由单个字母组成,则shell可以执行文件名扩展 nullgob 已设定。 tr "[A-Z]" "[a-z]" A 会表现得很好 - Dennis
@CamiloMartin这是一个BusyBox系统,我遇到了这个问题,特别是Synology NASes,但我也在其他几个系统上遇到过它。我最近一直在做很多跨平台的shell脚本,并且要求不需要额外安装它会让事情变得非常棘手!但是我还没有遇到没有的系统 sed - Haravikk
注意 tr [A-Z] [a-z] 在几乎所有语言环境中都不正确。例如,在 en-US 语言环境, A-Z 实际上是间隔 AaBbCcDdEeFfGgHh...XxYyZ。 - fuz


我知道这是一个古老的帖子,但我为另一个网站做了这个答案所以我想我会在这里发布:

上涨 - >下降: 使用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'`

或者Bash 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'`

或者Bash 4:

b=${a^^}

或NodeJS,如果你有它(并且有点疯狂......):

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

你也可以使用 dd (但我不会!):

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

当你说'贝壳'时,我假设你的意思 bash 但如果你可以使用 zsh 它就像

b=$a:l

小写和

b=$a:u

对于大写。


35
2018-05-14 09:36



sed命令和bash命令都不适合我。 - JESii
@JESii对我来说都是上层 - >下层和下层 - >上层。我在64位Debian Stretch上使用sed 4.2.2和Bash 4.3.42(1)。 - nettux443
嗨,@ nettux443 ...我刚刚再次尝试了bash操作,它仍然失败,错误信息“bad substitution”。我在OSX上使用自制软件的bash:GNU bash,版本4.3.42(1)-release(x86_64-apple-darwin14.5.0) - JESii
不使用! 所有生成脚本的例子都非常脆弱;如果是的价值 a 包含单引号,您不仅会破坏行为,还会出现严重的安全问题。 - tripleee
我最喜欢sed解决方案,因为sed总是无处不在。 - Dudi Boy


在zsh中:

echo $a:u

得爱zsh!


26
2018-01-27 05:37



或$ a:l用于小写转换 - Scott Smedley
再添一个案例: echo ${(C)a} #Upcase the first char only - biocyberman


使用GNU sed

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

例:

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

16
2017-09-26 15:45





对于仅使用内置函数的标准shell(没有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}"
}

11
2018-01-21 10:27



我想知道你是不是在这个脚本中没有让一些玄力,因为它在FreeBSD上不可移植sh:$ {1:$ ...}:错误替换 - Dereckson
确实;子串用 ${var:1:1} 是一种基督教。 - tripleee
这种方法的性能指标非常糟糕。请参阅我的指标答案。 - Dejay Clayton


Pre Bash 4.0

Bash降低字符串的大小写并赋值给变量

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

echo "$VARIABLE"

10
2018-01-24 13:53



没必要 echo 和管道:使用 $(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE") - Tino
@Tino这里的字符串也不能移植到真正旧版本的Bash;我相信它是在v3中引入的。 - tripleee
@tripleee你是对的,它是在bash-2.05b中引入的 - 但这是我能在我的系统上找到的最老的bash - Tino