简体   繁体   English

小写+大写+连接shell中字符串的单词(例如bash)

[英]lowercase + capitalize + concatenate words of a string in shell (e.g. bash)

How to capitalize+concatenate words of a string? 如何大写+连接字符串的单词?
(first letter uppercase and all other other letters lowercase) (首字母大写,所有其他字母小写)

example: 例:
input = "jAMeS bOnD"
output = "JamesBond"

String manipulation available in version 4: 版本4中可用的字符串操作:

  • ${variable,,} to lowercase all letters ${variable,,}以小写所有字母
  • ${variable^} to uppercase first letter of each word ${variable^}到每个单词的大写第一个字母
  • use ${words[*]^} instead of ${words[@]^} to save some script lines 使用${words[*]^}而不是${words[@]^}来保存一些脚本行

And other improvements from mklement0 (see his comments): mklement0的其他改进(见他的评论):

  • Variable names in lower-case because upper-case ones may conflict with environment variables 小写的变量名称,因为大写的名称可能与环境变量冲突
  • Give meaningful names to variables (eg ARRAY -> words ) 为变量赋予有意义的名称(例如ARRAY - > words
  • Use local to avoid impacting IFS outside the function (once is enougth) 使用local来避免在函数外部影响IFS (一次是enougth)
  • Use local for all other local variables ( variable can be first declared, and later assigned) 对所有其他局部变量使用local (可以先声明变量,然后再分配)
  • ARRAY=( $LOWERCASE ) may expands globs (filename wildcards ) ARRAY=( $LOWERCASE )可能会扩展globs (文件名通配符
    • temporarily disable Pathname Expansion using set -f or shopt -so noglob 使用set -fshopt -so noglob暂时禁用路径名扩展
    • or use read -ra words <<< "$input" instead of words=( $input ) 或者使用read -ra words <<< "$input"而不是words=( $input )

Ultimate function: 终极功能:

capitalize_remove_spaces()
{
  local words IFS
  read -ra words <<< "${@,,}"
  IFS=''
  echo "${words[*]^}"
}

If you want to keep alphanumeric characters only, extends the IFS built-in variable just before the read -ra words operation: 如果只想保留字母数字字符,请在read -ra words操作之前扩展IFS内置变量

capitalize_remove_punctuation()
{
  local words IFS=$' \t\n-\'.,;!:*?' #Handle hyphenated names and punctuation
  read -ra words <<< "${@,,}"
  IFS=''
  echo "${words[*]^}"
}

Examples: 例子:

> capitalize_remove_spaces 'jAMeS bOnD'
JamesBond

> capitalize_remove_spaces 'jAMeS bOnD *'
JamesBond*

> capitalize_remove_spaces 'Jean-luc GRAND-PIERRE'
Jean-lucGrand-pierre

> capitalize_remove_punctuation 'Jean-luc GRAND-PIERRE'
JeanLucGrandPierre

> capitalize_remove_punctuation 'Jean-luc GRAND-PIERRE *'
JeanLucGrandPierre

From other posts, I came up with this working script: 从其他帖子中,我想出了这个工作脚本:

str="jAMeS bOnD"
res=""
split=`echo $str | sed -e 's/ /\n/g'` # Split with space as delimiter
for word in $split; do
    word=${word,,} # Lowercase
    word=${word^} # Uppercase first letter
    res=$res$word # Concatenate result
done

echo $res

References: 参考文献:

Using awk it is little verbose but does the job:: 使用awk它有点冗长,但做的工作::

s="jAMeS bOnD"
awk '{for (i=1; i<=NF; i++)  
   printf toupper(substr($i, 1, 1)) tolower(substr($i,2)); print ""}' <<< "$s"
JamesBond

Here's a bash 3+ solution that utilizes tr for case conversion (the case conversion operators ( , , ^ , ...) were introduced in bash 4 ): 这里有一个bash 3+解决方案 ,利用tr的情况下转换(大小写转换操作符( ,^ ,...)中引入bash 4):

input="jAMeS bOnD"

read -ra words <<<"$input" # split input into an array of words
output="" # initialize output variable
for word in "${words[@]}"; do # loop over all words
  # add capitalized 1st letter
  output+="$(tr '[:lower:]' '[:upper:]' <<<"${word:0:1}")"
  # add lowercase version of rest of word
  output+="$(tr '[:upper:]' '[:lower:]' <<<"${word:1}")"
done

Note: 注意:

  • Concatenation (removal of whitespace between words) happens implicitly by always directly appending to the output variable. 连接(删除单词之间的空格)通过始终直接附加到输出变量隐式发生。
  • It's tempting to want to use words=( $input ) to split the input string into an array of words, but there's a gotcha: the string is subject to pathname expansion , so if a word happens to be a valid glob (eg, * ), it will be expanded (replaced with matching filenames), which is undesired; 想要使用words=( $input )将输入字符串拆分为单词数组是很诱人的,但是有一个问题:字符串受路径名扩展的影响 ,所以如果一个单词恰好是一个有效的glob(例如, * ),它将被扩展(替换为匹配的文件名),这是不希望的; using read -ra to create the array avoids this problem ( -a reads into an array, -r turns off interpretation of \\ chars. in the input). 使用read -ra创建数组避免了这个问题( -a读入数组, -r关闭输入中的\\ chars。的解释)。
echo -e '\n' "!!!!! PERMISSION to WRITE in  /var/log/ DENIED !!!!!"
echo -e '\n'
echo "Do you want to continue?"
echo -e '\n' "Yes or No"
read -p "Please Respond_: " Response #get input from keyboard "yes/no"
#Capitalizing 'yes/no' with # echo $Response | awk '{print toupper($0)}' or echo $Response | tr [a-z] [A-Z] 
answer=$(echo $Response | awk '{print toupper($0)}') 
case $answer in
    NO)
        echo -e '\n' "Quitting..."
        exit 1
        ;;
    YES)
        echo -e '\n' "Proceeding..."
        ;;
esac

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM