【问题标题】:uppercase first character in a variable with bashbash变量中的第一个字符大写
【发布时间】:2018-12-19 23:36:03
【问题描述】:

我想用 bash 将字符串中的第一个字符大写。

foo="bar";

//uppercase first character

echo $foo;

应该打印“酒吧”;

【问题讨论】:

标签: bash


【解决方案1】:

使用 bash 的一种方式(版本 4+):

foo=bar
echo "${foo^}"

打印:

Bar

【讨论】:

  • 与此相反吗?
  • @CMCDragonkai:要将第一个字母小写,请使用"${foo,}"。要将所有字母小写,请使用"${foo,,}"。要将所有字母大写,请使用"${foo^^}"
  • 无意间注意到${foo~}${foo~~}${foo^}${foo^^}的效果一样。但我从未在任何地方看到过这种替代方案。
  • 这似乎不适用于 Mac。收到以下错误:bad substitution
  • @TolandHon:您可能已经解决了,您需要升级到版本 4.x,或者如果该机器由于某种原因无法升级,请尝试其他解决方案。跨度>
【解决方案2】:
foo="$(tr '[:lower:]' '[:upper:]' <<< ${foo:0:1})${foo:1}"

【讨论】:

  • 尽管比得分最高的答案更复杂,但这个答案实际上就是这样做的:“变量中的第一个字符大写”。得分最高的答案没有该结果。看起来简单的答案比正确的答案更受欢迎?
  • @KrzysztofJabłoński:实际上,下面的“得分最高的答案”将产生与 Bash 4 下的答案相同的结果。这个答案有调用子外壳(另一个外壳)的开销,调用的开销'tr' 实用程序(另一个进程,不是 Bash),使用 here-doc/string(临时文件创建)的开销,并且与得分最高的答案相比,它使用了两个替换。如果您绝对必须编写遗留代码,请考虑使用函数而不是子shell。
  • 这个答案假设输入都是小写的。此变体没有假设: $(tr '[:lower:]' '[:upper:]'
  • @ItaiHanski OP没有指定其余字符应该发生什么,只有第一个。假设他们想将notQuiteCamel 更改为NotQuiteCamel。您的变体具有副作用或迫使其余部分变为小写 - 代价是子 shell 和 tr 进程的数量增加了一倍。
  • @DanieleOrlando,是的,但是这个问题除了bash 之外没有其他标签。
【解决方案3】:

sed 的一种方式:

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

打印:

Bar

【讨论】:

  • 在 MacOS10 Lion sed 上不起作用,唉,\u 扩展为 u 而不是运算符。
  • @vwvan brew install coreutils gnu-sed 并按照说明使用不带前缀 g 的命令。值得一提的是,自从获得 GNU 版本以来,我从未想过运行这些命令的 OSX 版本。
  • @Dean:FWIW,我从没想过运行 OSX :-)
  • 只需将其更改为 sed 's/./\U&amp;/ 即可在 POSIX sed 上运行。
  • @DavidConrad echo "bar" | sed 's/./\U&amp;/' 在 mac 上生成 Ubar。我认为\U 不是 POSIX 标准,而是 GNU 扩展。
【解决方案4】:
$ foo="bar";
$ foo=`echo ${foo:0:1} | tr  '[a-z]' '[A-Z]'`${foo:1}
$ echo $foo
Bar

【讨论】:

    【解决方案5】:

    仅将第一个单词大写:

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

    O二三


    将变量中的每个单词大写:

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

    O一个T两个T三个


    (适用于 bash 4+)

    【讨论】:

    • foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) 每个单词的分辨率更短。 foo 现在是“一二三”
    • 如何将前 3 或 4 个字母大写为大写?喜欢 pqrs-123-v1PQRS-123-v1 吗?或者你可以说,第一个连字符之前的所有字母...
    • 这个简单又完美。
    【解决方案6】:

    这里是“原生”文本工具方式:

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

    【讨论】:

    • 终于可以在 Mac 上使用变量了!谢谢!
    • @DanieleOrlando,不像人们希望的那样便携。如果tr [:lower:] [:upper:] 需要在包含不在a-zA-Z 范围内的字母的语言/区域设置中工作,那么tr [:lower:] [:upper:] 是一个更好的选择。
    【解决方案7】:

    仅使用 awk

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

    【讨论】:

    • 结果:未大写的字符串
    • 看着这个像?️??️
    【解决方案8】:

    也可以使用 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,作业中= 周围没有空格。这是shellcheck.net 会以编程方式为您找到的东西。
    • 我总是忘记 shell 脚本。只有一个空格(之前/之后)很重要的语言...叹息(如果我没记错的话,python 至少是 4)
    • @OZZIE,它必须,因为如果它不重要,你不能将= 作为参数传递给程序(它应该如何要知道someprogram = 是在运行someprogram,还是分配给一个名为someprogram 的变量?)
    【解决方案9】:

    你在这里只是为了好玩:

    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&/'
    

    【讨论】:

    • 感谢 AFAICT,唯一 解决方案不涉及 GNUisms。
    • (具体来说,awk 解决方案适用于任何符合 POSIX 的 awk。)
    • 这适用于 MacOS 和 ZSH。
    【解决方案10】:

    这也有效...

    FooBar=baz
    
    echo ${FooBar^^${FooBar:0:1}}
    
    => Baz
    
    FooBar=baz
    
    echo ${FooBar^^${FooBar:1:1}}
    
    => bAz
    
    FooBar=baz
    
    echo ${FooBar^^${FooBar:2:2}}
    
    => baZ
    

    等等。

    来源:

    介绍/教程:

    【讨论】:

      【解决方案11】:

      这个对我有用:

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

      例如:test.php => Test.php

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

      【讨论】:

      • 原来的问题是一个字符串,并没有提到重命名文件。
      【解决方案12】:

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

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

      返回 Abc

      【讨论】:

        【解决方案13】:
        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
        }
        

        第一个字母到下层-xc(){ v-首字母向下 | xclip -选择剪贴板 }

        【讨论】:

          【解决方案14】:

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

          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
          

          【讨论】:

            【解决方案15】:

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

            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=
            

            【讨论】:

            • 请编写更简洁的代码!你缺少引号到处都是。你正在使用过时的语法(反引号);您使用的是过时的语法 ($[...])。你使用了很多无用的括号。您假设字符串由拉丁字母表中的字符组成(重音字母或其他字母表中的字母怎么样?)。您需要做大量工作才能使这个 sn-p 可用! (并且由于您使用的是正则表达式,因此您不妨使用正则表达式来查找第一个字母,而不是循环)。
            • 我认为你错了。这是伴随反对票的强制性评论,解释了答案的所有错误模式和误解。请从你的错误中吸取教训(在此之前,尝试理解它们)而不是固执。做一个好人也与传播不良做法不相容。
            • 或者,如果使用 Bash ≥4,则不需要 tr: if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
            • 这段代码仍然严重损坏。它仍然使用反引号而不是现代替换语法;它仍然有无与伦比的报价;它仍然缺少引号在它们实际上很重要的地方;等等。如果您不相信那些缺少的引号会产生影响,请尝试将一些空格包围的全局字符放入您的测试数据中,并修复shellcheck.net 发现的问题,直到此代码干净为止。
            • 至于您从unix.stackexchange.com/questions/68694/… 引用的语言,您错过的是echo $foo解析器需要一个单词列表 的情况示例;所以在你的echo ${F} 中,F 的内容是字符串拆分和全局扩展的。对于echo ${S:$N:1} 示例和所有其他示例也是如此。见BashPitfalls #14
            猜你喜欢
            • 2012-09-07
            • 1970-01-01
            • 2019-08-19
            • 1970-01-01
            • 2011-01-26
            • 2023-02-23
            • 1970-01-01
            • 2015-07-24
            相关资源
            最近更新 更多