bash变量中的大写第一个字符


Answers:


148
foo="$(tr '[:lower:]' '[:upper:]' <<< ${foo:0:1})${foo:1}"

2
尽管比得分最高的答案要复杂得多,但实际上它确实做到了:“在变量中使用大写的第一个字符”。得分最高的答案没有该结果。看起来简单答案比正确答案更愿意被支持?
KrzysztofJabłoński'16

15
@KrzysztofJabłoński:实际上,下面的“得分最高的答案”将产生与Bash 4下的答案相同的结果。该答案具有调用子外壳程序(另一个外壳程序)的开销,以及调用“ tr”实用程序的开销(另一个过程) ,而不是Bash),这是使用Here-doc / string(临时文件创建)的开销,并且与得分最高的答案相比,它使用了两次替换。如果您绝对必须编写旧版代码,请考虑使用函数而不是子Shell。
史蒂夫(Steve)

2
该答案假定输入全部为小写。此变体没有假设:$(tr'[:lower:]''[:: upper:]'<<< $ {foo:0:1})$(tr'[:: upper:]''[:: lower: ]'<<< $ {foo:1})
Itai Hanski

5
@ItaiHanski OP未指定其余字符(仅第一个)会发生什么情况。假设他们想notQuiteCamel变成NotQuiteCamel。您的变体会产生副作用或将其余部分强制转换为小写形式-代价是将子shell和tr进程的数量加倍。
杰西·奇斯霍尔姆

3
@DanieleOrlando,是的,但是这个问题除了之外没有其他标签bash
Charles Duffy

313

bash(版本4+)的一种方法:

foo=bar
echo "${foo^}"

印刷品:

Bar

2
与此相反吗?
CMCDragonkai 2015年

44
@CMCDragonkai:要小写第一个字母,请使用"${foo,}"。要小写所有字母,请使用"${foo,,}"。要大写所有字母,请使用"${foo^^}"
史蒂夫

1
我不小心注意到了,${foo~}并且${foo~~}效果与${foo^}和相同 ${foo^^}。但是我从未见过任何地方提到过这种选择。
mivk

5
这似乎不适用于Mac。出现以下错误:bad substitution
Toland Hon

1
@TolandHon:您可能已经解决了,您需要升级到4.x版本,或者如果由于某种原因而无法升级该计算机,则尝试其他解决方案。
史蒂夫,

29

一种方法sed

echo "$(echo "$foo" | sed 's/.*/\u&/')"

印刷品:

Bar

10
在MacOS10 Lion sed上不起作用,叹气,\ u扩展为u而不是操作员。
vwvan 2014年

2
@vwvan brew install coreutils gnu-sed并按照说明使用不带前缀的命令g。自从获得GNU版本以来,我从未想过要运行这些命令的OSX版本。
教务长

@vwvan:是的,很抱歉,sed在这种情况下,您将需要GNU
Steve

2
@Dean:FWIW,我从没想过要运行OSX :-)
Steve

5
只需将其更改为,即可sed 's/./\U&/在POSIX sed上使用。
戴维·康拉德


14

这是“本机”文本工具的方式:

#!/bin/bash

string="abcd"
first=`echo $string|cut -c1|tr [a-z] [A-Z]`
second=`echo $string|cut -c2-`
echo $first$second

最后在Mac上可以使用变量的东西!谢谢!
OZZIE

4
@DanieleOrlando,不像人们希望的那样可移植。tr [:lower:] [:upper:]如果需要使用包含不在a-zA-Z范围内的字母的语言/语言环境,则是一个更好的选择。
Charles Duffy

8

仅使用awk

foo="uNcapItalizedstrIng"
echo $foo | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}'

结果:无大写字母的字符串
Alex Freshmann

4

也可以使用bash-3.2在纯bash中完成:

# First, get the first character.
fl=${foo:0:1}

# Safety check: it must be a letter :).
if [[ ${fl} == [a-z] ]]; then
    # Now, obtain its octal value using printf (builtin).
    ord=$(printf '%o' "'${fl}")

    # Fun fact: [a-z] maps onto 0141..0172. [A-Z] is 0101..0132.
    # We can use decimal '- 40' to get the expected result!
    ord=$(( ord - 40 ))

    # Finally, map the new value back to a character.
    fl=$(printf '%b' '\'${ord})
fi

echo "${fl}${foo:1}"

如何定义foo?我尝试过foo = $1但只得到-bash: foo: command not found
OZZIE

1
@OZZIE,=作业中的空格周围。这是shellcheck.net会以编程方式为您找到的东西。
Charles Duffy

我总是忘记了shell脚本..只有一个空格(前后)重要的语言...感叹(如果我没记错的话,python至少是4)
OZZIE

@OZZIE,它已经无关紧要,因为如果没有的事,你不能传递=作为参数传递给一个程序(它应该是怎样知道是否someprogram =正在运行someprogram,或分配给一个指定的变量someprogram?)
查尔斯达菲


3

只用首字母大写:

foo='one two three'
foo="${foo^}"
echo $foo

二三


要大写变量中的每个单词

foo="one two three"
foo=( $foo ) # without quotes
foo="${foo[@]^}"
echo $foo

Ø NE 牛逼 WO 牛逼重稀土


(适用于bash 4+)


foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) 每个单词的分辨率更短。foo现在是“一二三”
vr286 '18

2

适用于Linux和OSX的替代解决方案,也可以与bash变量一起使用

python -c "print(\"abc\".capitalize())"

返回Abc


0

这个为我工作:

搜索当前目录中的所有* php文件,并将每个文件名的第一个字符替换为大写字母:

例如:test.php => Test.php

for f in *php ; do mv "$f" "$(\sed 's/.*/\u&/' <<< "$f")" ; done

4
最初的问题是一个字符串,没有引用重命名文件。
AndySavage

0

只是为了好玩,您在这里:

foo="bar";    

echo $foo | awk '{$1=toupper(substr($1,0,1))substr($1,2)}1'
# or
echo ${foo^}
# or
echo $foo | head -c 1 | tr [a-z] [A-Z]; echo $foo | tail -c +2
# or
echo ${foo:1} | sed -e 's/^./\B&/'

0

不完全是什么要求,但很有帮助

declare -u foo #When the variable is assigned a value, all lower-case characters are converted to upper-case.

foo=bar
echo $foo
BAR

与之相反

declare -l foo #When the variable is assigned a value, all upper-case characters are converted to lower-case.

foo=BAR
echo $foo
bar

-1
first-letter-to-lower () {
        str="" 
        space=" " 
        for i in $@
        do
                if [ -z $(echo $i | grep "the\|of\|with" ) ]
                then
                        str=$str"$(echo ${i:0:1} | tr  '[A-Z]' '[a-z]')${i:1}$space" 
                else
                        str=$str${i}$space 
                fi
        done
        echo $str
}
first-letter-to-upper-xc () {
        v-first-letter-to-upper | xclip -selection clipboard
}
first-letter-to-upper () {
        str="" 
        space=" " 
        for i in $@
        do
                if [ -z $(echo $i | grep "the\|of\|with" ) ]
                then
                        str=$str"$(echo ${i:0:1} | tr  '[a-z]' '[A-Z]')${i:1}$space" 
                else
                        str=$str${i}$space 
                fi
        done
        echo $str
}

v-first-leter-to-lower | xclip-选择剪贴板}


-7

如果第一个字符不是字母(而是一个制表符,一个空格和一个转义的双引号)怎么办?我们最好先进行测试直到找到一封信!所以:

S='  \"ó foo bar\"'
N=0
until [[ ${S:$N:1} =~ [[:alpha:]] ]]; do N=$[$N+1]; done
#F=`echo ${S:$N:1} | tr [:lower:] [:upper:]`
#F=`echo ${S:$N:1} | sed -E -e 's/./\u&/'` #other option
F=`echo ${S:$N:1}
F=`echo ${F} #pure Bash solution to "upper"
echo "$F"${S:(($N+1))} #without garbage
echo '='${S:0:(($N))}"$F"${S:(($N+1))}'=' #garbage preserved

Foo bar
= \"Foo bar=

6
请编写更干净的代码!您到处都缺乏报价您正在使用过时的语法(反引号);您正在使用过时的语法($[...])。您正在使用许多无用的括号。您假设字符串由拉丁字母中的字符组成(重音字母还是其他字母的字母呢?)。您需要进行大量工作才能使此代码段可用!(由于您使用的是正则表达式,因此不妨使用正则表达式来查找第一个字母,而不是循环)。
gniourf_gniourf

6
我认为你错了。否决票附带有强制性评论,解释了答案的所有错误模式和误解。请从错误中学习(在此之前,尝试理解错误),而不要固执。做一个好人也与传播不良做法不相容。
gniourf_gniourf

1
或者,如果使用trif [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
Bash≥4

5
此代码仍然严重损坏。它仍然使用反引号代替现代替换语法。它仍然有无与伦比的报价;在实际上重要的地方仍然缺少引号; 等。如果您不相信这些缺失的引号会有所不同,请尝试在测试数据中添加一些用空格括起来的glob字符,并解决shellcheck.net发现的问题,直到此代码干净为止。
Charles Duffy

2
至于您从unix.stackexchange.com/questions/68694/…引用的语言,您错过的是解析器期望单词列表的echo $foo例子; 因此,在您的中,的内容是字符串分割和glob-expanded。对于该示例和所有其他示例也是如此。参见BashPitfalls#14echo ${F}Fecho ${S:$N:1}
Charles Duffy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.