bash中有没有将字符串转换为小写字符串的方法?
例如,如果我有:
a="Hi all"
我想将其转换为:
"hi all"
bash中有没有将字符串转换为小写字符串的方法?
例如,如果我有:
a="Hi all"
我想将其转换为:
"hi all"
当前回答
这不是比一个完整的shell变量链+声明+求值+单引号转义+echo+管道+tr更干净吗?
#***仅对于ASCII更快***mawk‘$!NF=上限($_)'<<<'abcxyz'
ABCXYZ
gawk“$_=tolower($_)”<<<“FAB-EDC”
fab-edc
和Unicode一样容易使用,无需“解包”、“编码”或“解码”字节
printf“%s”“${test_utf8}”|……
1 ÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øù
úûüýþÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪī
ĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝ
ŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏ
ƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀǁǂ
ǃDŽDždžLJLjljNJNjnjǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴ
……|gawk“$_=toupper($_)”
1 ÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙ
ÚÛÜÝÞŸĀĀĂĂĄĄĆĆĈĈĊĊČČĎĎĐĐĒĒĔĔĖĖĘĘĚĚĜĜĞĞĠĠĢĢĤĤĦĦĨĨĪĪ
ĬĬĮĮİIIJIJĴĴĶĶĸĹĹĻĻĽĽĿĿŁŁŃŃŅŅŇŇʼnŊŊŌŌŎŎŐŐŒŒŔŔŖŖŘŘŚŚŜŜ
ŞŞŠŠŢŢŤŤŦŦŨŨŪŪŬŬŮŮŰŰŲŲŴŴŶŶŸŹŹŻŻŽŽSƀƁƂƂƄƄƆƇƇƉƊƋƋƍƎƏ
ƐƑƑƓƔǶƖƗƘƘƚƛƜƝȠƟƠƠƢƢƤƤƦƧƧƩƪƫƬƬƮƯƯƱƲƳƳƵƵƷƸƸƺƻƼƼƾǷǀǁǂ
ǃDŽDžDŽLJLjLJNJNjNJǍǍǏǏǑǑǓǓǕǕǗǗǙǙǛǛƎǞǞǠǠǢǢǤǤǦǦǨǨǪǪǬǬǮǮǰDZDzDZǴ
其他回答
如果使用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},即使字符串有引号,也可以使用此函数。
对于仅使用内置的标准外壳(没有bashms):
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}"
}
许多答案使用外部程序,而不是真正使用Bash。
如果你知道你将有Bash4可用,你真的应该使用${VAR,,}符号(这很简单,很酷)。对于Bash before 4(例如,我的Mac仍然使用Bash 3.2)。我使用@ghostdog74的答案的修正版本创建了一个更便携的版本。
一个可以称为小写的“我的字符串”并获得小写版本。我阅读了关于将结果设置为var的评论,但这在Bash中不是真正可移植的,因为我们不能返回字符串。打印它是最好的解决方案。使用类似于var=“$(小写$str)”的内容很容易捕获。
这是如何工作的
其工作方式是通过printf获取每个字符的ASCII整数表示,然后如果上到->下加32,或者如果下到->上减32。然后再次使用printf将数字转换回字符。从“A”到->“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选项中使用此选项。
tr:
a="$(tr [A-Z] [a-z] <<< "$a")"
AWK:
{ print tolower($0) }
sed:
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
尽管这个问题有多古老,而且与技术龙的答案相似。我很难找到一个能够跨大多数平台(我使用的平台)以及旧版本bash移植的解决方案。我还对数组、函数以及使用prints、echo和临时文件来检索琐碎变量感到失望。到目前为止,这对我来说非常有效,我想我会分享。我的主要测试环境是:
GNUbash,版本4.1.2(1)-发布(x86_64-redhat-linux-GNU)GNUbash,版本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样式,用于遍历字符串。如果您以前没有看到过类似的内容,请选择下面的行这是我学到的。在这种情况下,该行检查输入中是否存在字符${input:$i:1}(小写),如果存在,则用给定的字符${ucs:$j:1}(大写)替换它,并将其存储回输入中。
input="${input/${input:$i:1}/${ucs:$j:1}}"