bash中有没有将字符串转换为小写字符串的方法?

例如,如果我有:

a="Hi all"

我想将其转换为:

"hi all"

当前回答

对于Bash命令行,根据语言环境和国际字母,这可能会起作用(根据其他人的答案组合而成):

$ echo "ABCÆØÅ" | python -c "print(open(0).read().lower())"
abcæøå
$ echo "ABCÆØÅ" | sed 's/./\L&/g'
abcæøå
$ export a="ABCÆØÅ" | echo "${a,,}"
abcæøå

尽管这些变化可能不起作用:

$ echo "ABCÆØÅ" | tr "[:upper:]" "[:lower:]"
abcÆØÅ
$ echo "ABCÆØÅ" | awk '{print tolower($1)}'
abcÆØÅ
$ echo "ABCÆØÅ" | perl -ne 'print lc'
abcÆØÅ
$ echo 'ABCÆØÅ' | dd conv=lcase 2> /dev/null
abcÆØÅ

其他回答

Bash 5.1提供了一种通过L参数转换实现这一点的直接方法:

${var@L}

例如,你可以说:

v="heLLo"
echo "${v@L}"
# hello

也可以使用U大写:

v="hello"
echo "${v@U}"
# HELLO

第一个字母用u大写:

v="hello"
echo "${v@u}"
# Hello

从bash手册页:

${参数^模式}${参数^^模式}${参数,模式}${参数,,模式}案例修改。此扩展修改参数中字母字符的大小写。该模式被扩展以生成模式,就像路径名扩展一样。展开的每个字符根据模式测试参数的值,如果匹配模式,其大小写被转换。该模式不应尝试匹配多个字符。^运算符转换为小写字母匹配模式到大写;运算符转换将大写字母匹配为小写字母。^^和,,展开式转换展开值中的每个匹配字符;这个^并且,展开式仅匹配并转换展开值中的第一个字符。如果省略了模式,则将其视为?, 它匹配每个字符。如果参数为@或*,则大小写修改操作将依次应用于每个位置参数,展开即为结果列表。如果参数是下标为@或*的数组变量,大小写修改操作应用于旋转,展开即为结果列表。

简单的方法

echo "Hi all" | awk '{ print tolower($0); }'

有多种方式:

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

Perl

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

Bash

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在这一个。即使使用shopt-u nocasematch;,也不适用于我(GNUbash版本4.2.46和4.0.33(行为2.05b.0相同,但没有实现nocasemach));。取消设置nocasematch会导致[[“fooBaR”==“fooBaR”]]与OK匹配,但奇怪的是,[b-z]与[A-z]不匹配。Bash被双重否定(“未设置nocasematch”)搞糊涂了!:-)

如果使用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},即使字符串有引号,也可以使用此函数。