假设我有一个变量,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 末尾替换为,导致匹配的部分存储在(即需要的部分)中并转换为小写。pattern
replacement
(#m)
$MATCH
extendedglob
${(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
答案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/)