Shellcheck 建议双引号变量在管道切割时不起作用

Shellcheck 建议双引号变量在管道切割时不起作用

我正在编写一个脚本来打印 ZFS 文件系统信息 - 目前处于测试阶段,但我收到了一个奇怪的错误。

我的初始脚本的相关部分如下:

zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo $zfs_human | cut -d ' ' -f2)"
zfs_totah="$(echo $dfs_human | cut -d ' ' -f2)"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"

给出以下输出:

zfs                      2.31M  5.27T     34.4K  /mnt/zfs
zfs                      5.3T  128K  5.3T   1% /mnt/zfs
2.31M
5.3T

但是,当我运行时shellcheck,它说我应该在命令替换中用双引号括住变量名,这是来自的输出shellcheck

In zfsspace.sh line 5:zfs_usedh="$(echo $zfs_human | cut -d ' ' -f2)"                  ^--------^
SC2086: Double quote to prevent globbing and word splitting.

Did you mean: 
zfs_usedh="$(echo "$zfs_human" | cut -d ' ' -f2)"

In zfsspace.sh line 6:zfs_totah="$(echo $dfs_human | cut -d ' ' -f2)"                  ^--------^
SC2086: Double quote to prevent globbing and word splitting.

Did you mean: 
zfs_totah="$(echo "$dfs_human" | cut -d ' ' -f2)"

然后我当然将我的代码更改为 shellcheck 的建议:

zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo "$zfs_human" | cut -d ' ' -f2)"
zfs_totah="$(echo "$dfs_human" | cut -d ' ' -f2)"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"

但现在输出是这样的:

zfs                      2.31M  5.27T     34.4K  /mnt/zfs
zfs                      5.3T  128K  5.3T   1% /mnt/zfs
 
 

第 3 行和第 4 行是空白,这意味着按照 shellcheck 的建议,第 3 行和第 4 行命令替换不起作用,但在不引用我回显的变量时起作用。

我在 Ubuntu 20.04.1 上使用 Bash 5.0.17

有人能解释一下吗?谢谢。

答案1

添加-H到 zfs 将删除标头并用单个制表符(而不是任意空格)分隔字段,这大大简化了解析。因为df没有删除标头的选项,所以findmnt这将是一个更好的选择。

#!/bin/bash

# zfs
read -r zfs_usedh < <(zfs list -H -o used)

# df
read -r zfs_totah < <(findmnt -frnt zfs -o size)

echo "$zfs_usedh"
echo "$zfs_totah"

没有总体规模,因此df,您必须依靠传统数学。

#!/bin/bash

read -d \\n -r avail used total < <(zfs get -Hpo value available,used | \
     awk 'NR < 3 { n+=$1; print $1 } END { print n }' | numfmt --invalid=ignore --to=iec \
)

printf %s\\n $used $total

答案2

根据@steeldrivers 的建议,我用 替换cutawk并且它按预期工作。

zfs_human="$(zfs list | head -n 2 | tail -n 1)"
dfs_human="$(df -h | grep 'zfs' | head -n 1)"
zfs_usedh="$(echo "$zfs_human" | awk -F " " '{print $2}')"
zfs_totah="$(echo "$dfs_human" | awk -F " " '{print $2}')"
echo "$zfs_human"
echo "$dfs_human"
echo "$zfs_usedh"
echo "$zfs_totah"

为了保持一致性,我相信这是保留 推荐的语法的最佳解决方案shellcheck,因此一致使用awk进行cut字符串拆分,除非有特殊原因需要使用cut

相关内容