【问题标题】:Getting Bad substitution error with a Shell Script on a mac?在 Mac 上使用 Shell 脚本出现错误替换错误?
【发布时间】:2018-05-28 16:15:57
【问题描述】:

每当我在 Mac OSX 终端中运行 shell 脚本时,我都会收到一条错误消息“./query.sh: line 5: ${1,,}: bad substitution”

#!/bin/bash
dir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )

if [ "$1" != "" ]; then
    letter1=$(echo ${1,,}|(cut -b1))new
    if [[ $letter1 == [a-zA-Z0-9] ]]; then
        if [ -f "$dir/data/$letter1" ]; then
            grep -ai "^$1" "$dir/data/$letter1"
        else
            letter2=$(echo ${1,,}|cut -b2)
            if [[ $letter2 == [a-zA-Z0-9] ]]; then
                if [ -f "$dir/data/$letter1/$letter2" ]; then
                    grep -ai "^$1" "$dir/data/$letter1/$letter2"
                else
                    letter3=$(echo ${1,,}|cut -b3)
                    if [[ $letter3 == [a-zA-Z0-9] ]]; then
                        if [ -f "$dir/data/$letter1/$letter2/$letter3" ]; then
                            grep -ai "^$1" "$dir/data/$letter1/$letter2/$letter3"
                        fi
                    else
                        if [ -f "$dir/data/$letter1/$letter2/symbols" ]; then
                            grep -ai "^$1" "$dir/data/$letter1/$letter2/symbols"
                        fi
                    fi
                fi
            else
                if [ -f "$dir/data/$letter1/symbols" ]; then
                    grep -ai "^$1" "$dir/data/$letter1/symbols"
                fi
            fi
        fi
    else
        if [ -f "$dir/data/symbols" ]; then
            grep -ai "^$1" "$dir/data/symbols"
        fi
    fi
else
    echo "[*] Example: ./query name@domain.com"
fi

脚本的功能是搜索大量数据文件,所以有人可以帮我找出问题的根源吗?

【问题讨论】:

    标签: macos shell terminal sh posix


    【解决方案1】:

    ,, 运算符是在 bash 4.0 中引入的,但 macOS 上的 /bin/bash 仍然是 3.2 版。您可以安装更新版本的bash 并相应地更改您的shebang,或者您可以改用letter1=$(echo "$1" | tr '[:upper:]' '[:lower:]' | cut -b1)

    (但是,您可以使用${letter:0:1}${letter:1:1} 等代替调用cut 从字符串中获取单个字母。)

    我的建议是将 macOS 上的 /bin/bash 视为与 POSIX 兼容的 shell。如果您想要一个可移植的脚本,请使用#!/bin/sh,或者如果您想以牺牲可移植性为代价利用bash 扩展,请使用#!/usr/local/bin/bash(或任何合适的,在安装bash 的新版本之后)。

    【讨论】:

    • POSIX 字符类不应该只有一个方括号吗? tr 的参数是字符类,而不是正则表达式。 (当然,用[ 替换[ 是无害的。)
    • 谢谢,帮我解决了问题
    • @tripleee 我认为有一些 tr 版本需要额外的括号。我在“Unix Power Tools”中读到“在tr 的System V 版本中,方括号必须包围任何范围的字符”——但我同意可能大多数trs“在野外”支持单括号语法。
    • 哦,可能; tr 是我所知道的唯一一个不需要将字符类放在括号表达式中的程序。
    【解决方案2】:

    如果您使用 subshel​​l 来生成值,您不妨将调用更改为可移植回早期版本的 Bash 的东西。

    在子shell(括号中)中运行cut -b1 是没有用的,并且在转换之后执行它意味着您转换一个可能很长的字符串,然后丢弃除第一个字符之外的所有内容。

    letter1=$(echo "${1:0:1}" | tr '[:upper:]' '[:lower:]')new
    

    还要注意 echo 参数周围的双引号。

    您真的希望将后缀new 附加到值上吗?在这种情况下,if 中的第一个条件永远不会匹配。

    您可能还应该重构代码以避免深层"arrow antipattern",并且只有在您获得要搜索的文件名的值后才执行grep

    【讨论】:

    • 箭头反模式。不错的词!
    【解决方案3】:

    正如其他答案中提到的,Mac 上的内置 bash 非常旧,必须升级才能使用某些运算符,例如插入符运算符。如果您使用自制软件,请运行 brew install bash 并按照 this post 中的说明进行操作。

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      • 2016-04-04
      • 2019-12-01
      • 2023-03-11
      • 2019-11-14
      • 1970-01-01
      相关资源
      最近更新 更多