AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 443469
Accepted
jesse_b
jesse_b
Asked: 2018-05-13 13:58:45 +0800 CST2018-05-13 13:58:45 +0800 CST 2018-05-13 13:58:45 +0800 CST

为什么此代码在 bash v4.4 中有效,但在 bash v3.2 中无效?

  • 772

我有以下 bash 脚本:

#!/bin/bash

encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
MISSING_DISKS=()
OLDIFS=$IFS
IFS=$'\n'
MISSING_DISKS+=($({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${encl0[@]#0,}"; } | sort | uniq -u))
IFS=$OLDIFS
echo "$({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${encl0[@]#0,}"; } | sort | uniq -u)"
echo "${MISSING_DISKS[@]}"
if ((${#MISSING_DISKS[@]}>1)); then
    echo "Greater than 1"
else
    echo "Success"
fi

当我使用 bash v4.4 运行它时,它可以按预期工作:

$ /usr/local/bin/bash test.sh
0 6
0 6
Success

但是,当我使用 bash v3.2 运行它时,它不会:

$ /bin/bash test.sh
0 6
0 0 0 0 1 2 3 4 5 7 8 9 10 11 12 13 14 15 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9
Greater than 1

我不明白如何MISSING_DISKS设置为与设置它的命令的输出不同的东西。有谁知道是什么原因造成的?

bash shell-script
  • 1 1 个回答
  • 271 Views

1 个回答

  • Voted
  1. Best Answer
    user232326
    2018-05-13T18:55:10+08:002018-05-13T18:55:10+08:00

    使用空格、制表符或换行符总是接近于失败。

    核心问题出现在这里:

    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$'\n'
    printf '<0 %s>\n' "${encl0[@]#0,}"
    

    如果在 bash 3.2 上执行:

    $ b32sh ./script
    <0 0 1 2 3 4 5 7 8 9>
    

    的扩展"${encl0[@]#0,}"被处理为一个字符串,而不是值列表。

    如果 IFS 有空格或者扩展没有编辑数组的每个值,则问题不会出现:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$' \n'
    printf '<0 %s>\n' "${encl0[@]#0,}"
    

    执行:

    $ b32sh ./script
    <0 0>
    <0 1>
    <0 2>
    <0 3>
    <0 4>
    <0 5>
    <0 7>
    <0 8>
    <0 9>
    

    或者:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$'\n'
    printf '<0 %s>\n' "${encl0[@]}"
    

    执行:

    b32sh ./so
    <0 0,0>
    <0 0,1>
    <0 0,2>
    <0 0,3>
    <0 0,4>
    <0 0,5>
    <0 0,7>
    <0 0,8>
    <0 0,9>
    

    该问题隐藏在您的脚本中,因为您IFS=$OLDIFS 在测试回显行之前恢复 IFS。

    避免该问题的一种方法是不在 printf 中使用空格:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    MISSING_DISKS=()
    OLDIFS=$IFS
    IFS=$' \n'
    MISSING_DISKS+=($({ printf '0x%s\n' {0..15}; printf '0x%s\n' "${encl0[@]#0,}"; } | sort | uniq -u))
    echo "test $({ printf '0x%s\n' {0..15}; printf '0x%s\n' "${encl0[@]#0,}"; } | sort | uniq -u)"
    echo "var  ${MISSING_DISKS[@]}"
    if ((${#MISSING_DISKS[@]}>1)); then
        echo "Greater than 1"
    else
        echo "Success"
    fi
    IFS=$OLDIFS
    

    另一种选择是通过使用备用数组将 IFS 更改为换行符后避免使用替换进行扩展:

    #!/bin/bash
    OLDIFS=$IFS
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    IFS=$' \n'; arr=("${encl0[@]#0,}")
    MISSING_DISKS=()
    IFS=$'\n'
    MISSING_DISKS+=($({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${arr[@]}"; } | sort | uniq -u))
    echo "test $({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${arr[@]}"; } | sort | uniq -u)"
    echo "var  ${MISSING_DISKS[@]}"
    if ((${#MISSING_DISKS[@]}>1)); then
        echo "Greater than 1"
    else
        echo "Success"
    fi
    IFS=$OLDIFS
    

    我建议你:

    • 遵循 CAPS 中的变量是环境变量的规则。
    • 没有必要+=在代码中增加一个在该点为空的数组MISSING_DISKS+=。
    • 在 printf 中使用非空格字符以避免需要从 IFS 中删除空格。这使脚本更加健壮。

    如果完成了这些更改,脚本将变为:

    #!/bin/bash
    oldIFS=$IFS
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    unset missing_disks
    
    IFS=' '
               arr=($(printf '0-%s\n' "${encl0[@]#0,}"))
               arr+=($(printf '0-%s\n' {0..15}))
    
    missing_disks=($(printf '%s\n' "${arr[@]}" | sort | uniq -u))
    
               echo "test $(printf '0-%s\n' "${arr[@]}" | sort | uniq -u)"
               echo "var  ${missing_disks[@]}"
    
    ((${#missing_disks[@]}>1)) && echo "Greater than 1" || echo "Success"
    IFS=$oldIFS
    
    • 6

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve