仅将某些单词转换为小写

仅将某些单词转换为小写

假设我有一个变量,var其值为fOo bar1 baR2 bArab

我如何保存到另一个变量中,例如,除了第一个单词之外的所有单词都转换为小写lc_var的版本?var

我知道它可能看起来像lc_var=$(echo $var | ...), where ...will 被适当的 AWK 或 sed 命令替换。

答案1

带壳zsh

set -o extendedglob
lc_var=${var/%(#m) */${(L)MATCH}}

在 ksh 中,将与${var/%pattern/replacement}匹配的 var 末尾替换为,导致匹配的部分存储在(即需要的部分)中并转换为小写。patternreplacement(#m)$MATCHextendedglob${(L)MATCH}$MATCH

带壳bash

tmp1=${var%% *}
tmp2=${var#"$tmp1"}
lc_var=$tmp1${tmp2,,}

POSIXly,你会这样做:

lc_var=$(
  awk '
    BEGIN{
      var = ARGV[1]
      if (i = index(var, " "))
        var = substr(var, 1, i) tolower(substr(var, i + 1))
      print var "."
    }' "$var"
)
lc_var=${lc_var%.}

无论如何,这看起来都不可能是lc_var=$(echo $var ...)因为$(...)POSIX/Korn/bash/zsh shell 语法,并且在这些 shell 中,echo无法输出任意数据变量扩展应该被引用(也许除了zsh)。

所有这些变体都将第一个空格字符之后的所有字符转为小写$var(不假设它们可能是什么字符)。如果单词可能由空格以外的字符分隔,或者第一个单词之前可能有单词分隔符,则需要调整它。

答案2

bash

var='fOo bar1 baR2 bArab'
tail=${var#* }; lc_var="${var%% *} ${tail,,}"
echo "$lc_var"

fOo bar1 bar2 barab

作为一个函数:

set_lc(){ declare -n v=$1; declare t=${2#* }; v="${2%% *} ${t,,}"; }

或者:

set_lc(){ typeset -n _v=$1; typeset h=${2%% *}; typeset -l t=${2#"$h"}; _v=$h$t; }

(这个第二个版本也应该适用于ksh,并且将处理由单个单词组成的参数)

set_lc var 'FOO BAR BAZ'
echo "$var"

FOO bar baz

有关 bash 奇怪且有限的参数扩展的更多信息修饰语以及关于声明/排版在狂欢中手动的

答案3

以下解决方案使用 GNU sed 并且仅在 bash 中进行了测试。即使变量包含多行文本它也有效。

lc_var="$(printf "%s\n" "$var"|sed ':l;$!{N;bl};s:\s.*:\L&.:')"
lc_var="${lc_var%.}"

非常感谢 @Stéphane Chazelas 对边缘情况的讨论,例如 echo、sed -z、命令替换等。

答案4

lc_var=$(echo $var | sed 's/^\([^ ]*\)\(.*\)/\1\L\2/g')

(在一点帮助下http://timmerphy.org/2013/02/24/converting-to-uppercase-lowercase-in-sed/

相关内容