当前位置: 代码迷 >> 综合 >> 如何在Bash中将字符串转换为小写?
  详细解决方案

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

热度:63   发布时间:2023-09-06 13:23:32.0

bash中有一种方法可以将字符串转换为小写字符串?

例如,如果我有:

a="Hi all"

我想将其转换为:

"hi all"

#1楼

如果使用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} ,即使在字符串带引号的情况下也可以使用。

#2楼

对于4.0之前的Bash版本,此版本应该是最快的(因为它不会派生/执行任何命令):

function string.monolithic.tolower
{local __word=$1local __len=${#__word}local __charlocal __octallocal __decimallocal __resultfor (( 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"doneREPLY="$__result"
}

尽管技工龙的答案确实适合我,但它也有潜力。


#3楼

在bash 4中,您可以使用排版

例:

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

#4楼

前Bash 4.0

Bash减小字符串的大小写并分配给变量

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

#5楼

使用GNU sed

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

例:

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

#6楼

tr :

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

AWK :

{ print tolower($0) }

sed :

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

#7楼

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

#8楼

有多种方式:

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++))
doch="${word:$i:1}"lc "$ch"
done

注意:YMMV就此。 即使使用shopt -u nocasematch;它也对我不起作用(GNU bash版本4.2.46和4.0.33(具有相同的行为2.05b.0,但未实现nocasematch)) shopt -u nocasematch; 。 取消设置nocasematch会导致[[“” fooBaR“ ==” FOObar“]]奇怪地匹配[Bz]内的情况,但[AZ]错误地匹配了[Bz]。 Bash被双负数(“ uncasematch”)弄糊涂了! :-)


#9楼

在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所建议,添加了“按单词切换第一个字符”( ${var~} var? ${var~} )。

编辑:更正了波浪号行为,以匹配Bash 4.3。


#10楼

我知道这是一篇过时的文章,但是我在另一个网站上做了这个答案,所以我想把它张贴在这里:

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

下->上

使用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

大写。


#11楼

尽管这个问题有几岁了,而且与科技恐龙的答案相似 。 我很难找到一个可以在大多数平台(我使用的平台)以及较旧版本的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}" ]] ; theninput="${input/${input:$i:1}/${ucs:$j:1}}" fidone
done

简单的C风格的for循环遍历字符串。 对于下面的行,如果您在我学到这之前没有看到过这样的内容 。 在这种情况下,该行检查输入中是否存在char $ {input:$ i:1}(小写),如果存在,将其替换为给定的char $ {ucs:$ j:1}(大写)并存储它返回输入。

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

#12楼

将转换后的字符串存储到变量中。 以下项目对我$TARGET_NAME - $SOURCE_NAME$TARGET_NAME

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

#13楼

你可以试试这个

s="Hello World!" echo $s  # Hello World!a=${s,,}
echo $a  # hello world!b=${s^^}
echo $b  # HELLO WORLD!

参考: http : //wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/


#14楼

许多答案是使用外部程序的,而实际上不是使用Bash

如果您知道可以使用Bash4,则应该只使用${VAR,,}表示法(既简单又酷)。 对于4之前的Bash(例如,我的Mac仍使用Bash 3.2)。 我使用了@ ghostdog74的答案的更正版本来创建更可移植的版本。

您可以将lowercase 'my STRING'称为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++)); doch="${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++)); doch="${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')" ]]; thenecho "Fine! All the same!"
elseecho "Ops! Not the same!"
fiexit 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选项。


#15楼

正则表达式

我想赞扬我希望分享的命令,但事实是我从http://commandlinefu.com获得了供我自己使用的命令。 这样做的好处是,如果您cd到自己的主文件夹中的任何目录,它将以递归方式将所有文件和文件夹更改为小写,请谨慎使用。 这是一个出色的命令行修复程序,对于您存储在驱动器上的大量专辑特别有用。

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

您可以在查找后指定一个目录来代替点(。),它表示当前目录或完整路径。

我希望该解决方案证明是有用的,此命令不做的一件事就是用下划线替换空格-哦,也许还有一次。


#16楼

在zsh中:

echo $a:u

一定爱zsh!


#17楼

仅对字母进行大小写转换。 因此,这应该工作整齐。

我专注于将az的字母从大写转换为小写。 其他任何字符都应该按原样打印在标准输出中...

将z范围内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

#18楼

这是JaredTS486使用本地Bash功能(包括低于4.0的Bash版本)来优化其方法的方法的更快变化。

我已经为小字符串(25个字符)和大字符串(445个字符)定时了1000次此方法的迭代,无论是小写还是大写转换。 由于测试字符串主要是小写字母,因此转换为小写字母通常比转换为大写字母更快。

我已经将我的方法与本页上其他与Bash 3.2兼容的答案进行了比较。 我的方法比此处记录的大多数方法具有更高的性能,在某些情况下甚至比tr更快。

以下是25个字符的1,000次迭代的计时结果:

  • 我的小写字母为0.46s; 大写为0.96s
  • Orwellophile 的小写方法为1.16分 ; 大写1.59s
  • tr至小写字母为3.67秒; 大写3.81秒
  • ghostdog74 的小写方式为11.12秒 ; 大写31.41秒
  • Technosaurus 处理小写字母的时间为26.25s ; 大写26.21秒
  • JaredTS486 的小写方法为25.06秒 ; 大写27.04秒

445个字符的1,000次迭代的计时结果(由Witter Bynner的诗歌“ The Robin”组成):

  • 我的小写方法为2秒; 大写字母12s
  • tr小写为4s; 大写字母4s
  • Orwellophile的小写方法为20 秒 ; 大写字母29s
  • ghostdog74 的小写方式为75s ; 大写为669s。 有趣的是,在比赛占优势的测试与失误占优势的测试之间,性能差异有多大
  • techsausaurus的小写字母为467秒 ; 大写449s
  • JaredTS486 的小写方法为660s ; 大写660s。 有趣的是,这种方法在Bash中产生了连续的页面错误(内存交换)

解:

#!/bin/bash
set -e
set -udeclare LCS="abcdefghijklmnopqrstuvwxyz"
declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"function lcase()
{local TARGET="${1-}"local UCHAR=''local UOFFSET=''while [[ "${TARGET}" =~ ([A-Z]) ]]doUCHAR="${BASH_REMATCH[1]}"UOFFSET="${UCS%%${UCHAR}*}"TARGET="${TARGET//${UCHAR}/${LCS:${#UOFFSET}:1}}"doneecho -n "${TARGET}"
}function ucase()
{local TARGET="${1-}"local LCHAR=''local LOFFSET=''while [[ "${TARGET}" =~ ([a-z]) ]]doLCHAR="${BASH_REMATCH[1]}"LOFFSET="${LCS%%${LCHAR}*}"TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}"doneecho -n "${TARGET}"
}

这种方法很简单:当输入字符串中存在所有剩余的大写字母时,找到下一个字母,然后用小写字母替换该字母的所有实例。 重复直到所有大写字母都被替换。

我的解决方案的一些性能特征:

  1. 仅使用shell内置实用程序,从而避免了在新进程中调用外部二进制实用程序的开销
  2. 避免使用子壳,否则会导致性能下降
  3. 使用针对性能进行编译和优化的外壳程序机制,例如变量内的全局字符串替换,变量后缀修整以及正则表达式搜索和匹配。 这些机制比通过字符串手动迭代要快得多
  4. 仅循环计数要转换的唯一匹配字符数所需的次数。 例如,将具有三个不同大写字符的字符串转换为小写仅需要3次循环迭代。 对于预配置的ASCII字母,最大循环迭代次数为26
  5. UCSLCS可以增加其他字符

#19楼

如果您喜欢python并且可以选择安装新的python软件包,则可以尝试使用此python实用工具 。

# install pythonp
$ pip install pythonp$ echo $a | pythonp "l.lower()"

#20楼

简单的方法

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

#21楼

对于仅使用内置函数的标准外壳程序(没有bashisms):

uppers=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lowers=abcdefghijklmnopqrstuvwxyzlc(){ #usage: lc "SOME STRING" -> "some string"i=0while ([ $i -lt ${#1} ]) doCUR=${1:$i:1}case $uppers in*$CUR*)CUR=${uppers%$CUR*};OUTPUT="${OUTPUT}${lowers:${#CUR}:1}";;*)OUTPUT="${OUTPUT}$CUR";;esaci=$((i+1))doneecho "${OUTPUT}"
}

对于大写:

uc(){ #usage: uc "some string" -> "SOME STRING"i=0while ([ $i -lt ${#1} ]) doCUR=${1:$i:1}case $lowers in*$CUR*)CUR=${lowers%$CUR*};OUTPUT="${OUTPUT}${uppers:${#CUR}:1}";;*)OUTPUT="${OUTPUT}$CUR";;esaci=$((i+1))doneecho "${OUTPUT}"
}
  相关解决方案