在bash中每个字母定义变量的回声不同

问题描述:

我的队友之前在unix SE上问过这个问题,但他问的是错误的。他也没有得到正确的答案。在bash中每个字母定义变量的回声不同

无论如何,我试图让我的bash脚本处理变量中的每个字符,并且每个字母都回显特定的字符串,直到达到最后。这是我到目前为止有:

#!/bin/bash 

echo Word? 
read -r -p '' foo 
# $foo is set to 'Mammals and Bricks' by user. 

wordlength=${#foo} 
$wordlength says 18, so start on character 1. 
'M' is first letter received in $foo, so echo '{m,M}' 
'a' is second letter received in $foo, so echo '{a,A}' 
'm' is third letter received in $foo, so echo '{m,M}' 
'm' is fourth letter received in $foo, so echo '{m,M}' 
'a' is the fifth letter received in $foo, so echo '{a,A}' 
'l' is the sixth letter received in $foo, so echo '{l,L}' 
's' is the seventh letter received in foo, so echo '{s,S}' 
' ' is the eighth, so echo '\ ' 
........ 
'c' is sixteenth letter received in $foo, so echo '{c,C}' 
'k' is seventeenth letter received in $foo, so echo '{k,K}' 
's' is eighteenth letter received in $foo, so echo '{s,S}' 

这里是它会是什么样子对用户端:

Word? 

哺乳动物和砖

{m,M}{a,A}{m,M}{m,M}{a,A}{l,L}{s,S} {a,A}{n,N}{d,D} {b,B}{r,R}{i,I}{c,C}{k,K}{s,S} 

哪个会是什么输出恰好为。你会看到所有上面的原始字符。

任何人都知道如何做到这一点?

开始通过在字符串中的字符循环:

foo=string 
for ((i=0; i<${#foo}; i++)); do 
    echo "${foo:$i:1}" 
done 

(参考:How to perform a for loop on each character in a string in BASH?

现在用case语句替换回声声明:

foo=string 
for ((i=0; i<${#foo}; i++)); do 
    case "${foo:$i:1}" in 
    a) 
     echo "Do something with a here"; 
     ;; 
    [bB]) 
     echo "Do something with b or B here"; 
     ;; 
    esac 
done 

下面是一个解决方案与GNU sed,如果你不介意使用它:

sed 's/[a-zA-Z]/{\l&,\u&}/g' <<< "$foo" 

\l\u是GNU扩展到sed,分别将下一个字符转为小写和大写。

[编辑]这里是bash一个解决方案,因为你没有GNU sed

while read -r -n1; do 
    if [[ "${REPLY^}" == [A-Z] ]]; then 
     printf '{%c,%c}' "${REPLY,}" "${REPLY^}" 
    else 
     printf '%c' "$REPLY" 
    fi 
done <<< "$foo" 
echo 

[编辑]附:不幸的是,这在OS X Yosemite上不起作用,因为$ {var,}和$ {var ^}结构是在bash v4中添加的,但是MacOS仅随bash v3.2.57一起发布(这是因为bash v4在GPL v3,Apple不想遵守)。感谢@GordonDavisson为此添加。

因此,这里是应该与你的bash v3上运行的解决方案:

printf '%s\n' "$foo" \ 
| while read -d '' -r -n1; do 
    lowercase="$(printf '%c' "$REPLY" | tr '[:upper:]' '[:lower:]')" 
    uppercase="$(printf '%c' "$REPLY" | tr '[:lower:]' '[:upper:]')" 
    if [ "$lowercase" != "$uppercase" ]; then 
     printf '{%c,%c}' "$lowercase" "$uppercase" 
    else 
     printf '%c' "$REPLY" 
    fi 
done 
+0

嗯......当我跑我的输出是这样的:'{LM,UM} {LA,UA} {LM ,um} {lm,um} {la,ua} {ll,ul} {ls,us} {la,ua} {ln,un} {ld,ud} {lB,uB} {lr,ur} {li ,UI} {LC,UC} {LK,英国} {LS,我们}'。我使用OS X Yosemite btw – leetbacoon

+0

然后你可能使用的是经典的sed,而不是GNU sed(注意GNU sed可能在OSX上可用)。我在纯bash中添加了一个解决方案。 – xhienne

+1

@xhienne不幸的是,'$ {var,}'和'$ {var ^}'构造是在bash v4中添加的,但是macOS只随bash v3.2.57一起发布。 (这是因为bash v4是根据GPL v3获得许可的,苹果不想遵守。) –