【问题标题】:Echo different text per letter of a defined variable in bash在 bash 中为定义的变量的每个字母回显不同的文本
【发布时间】:2017-08-20 23:02:38
【问题描述】:

我的伙伴之前在 unix SE 上问过这个问题,但他问错了。他也没有得到有效的答案。

无论如何,我正在尝试让我的 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}

确切会输出什么。您会以原始字符形式看到上述所有内容。

有人知道怎么做吗?

【问题讨论】:

    标签: bash osx-yosemite


    【解决方案1】:

    以下是 GNU sed 的解决方案,如果您不介意使用它:

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

    \l\used 的 GNU 扩展,它们分别将下一个字符变为小写和大写。

    [编辑] 这里是 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
    

    【讨论】:

    • 嗯...当我运行时,我的输出如下所示:{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,uk}{ls,us}。我正在使用 OS X Yosemite 顺便说一句
    • 那么您可能使用的是经典的 sed,而不是 GNU sed(请注意,GNU sed 可能在 OSX 上可用)。我在纯 bash 中添加了一个解决方案。
    • @xhienne 不幸的是,${var,}${var^} 结构是在 bash v4 中添加的,但 macOS 仅附带 bash v3.2.57。 (这是因为 bash v4 是在 GPL v3 下获得许可的,Apple 不想遵守。)
    • @GordonDavisson 感谢您的有趣评论。我会修改我的答案。
    • 好吧,既然通过优胜美地的终端无法做到这一点,有没有其他方法可以做到这一点?
    【解决方案2】:

    首先循环遍历字符串中的字符:

    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 语句替换 echo 语句:

    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
    

    【讨论】:

      猜你喜欢
      • 2019-02-16
      • 2013-09-20
      • 2015-11-17
      • 2015-06-21
      • 2011-04-27
      • 2015-01-28
      • 2022-10-15
      • 1970-01-01
      • 2017-01-04
      相关资源
      最近更新 更多