bash + 如何将 arg 与 Linux 机器中的磁盘之一进行比较

bash + 如何将 arg 与 Linux 机器中的磁盘之一进行比较

我可以使用以下命令捕获 Linux 机器的磁盘设备:

lsblk -lnb | numfmt --to=iec --field=4 | grep disk | awk '{print $1}'
sda
sdb
sdc
sdd

在我的 bash 脚本中,我使用下面的行来测试脚本的参数是否与我的计算机上的磁盘之一匹配:

if [[ ` lsblk -lnb | numfmt --to=iec --field=4 | grep disk | awk '{print $1}' | grep -c $arg ` != 0 ]] 
then
echo “argument is a disk”
.
.
.

fi

我运行脚本为

bash /tmp/verify_disks  <some arg>

但如果 case$arg被误认为arg=”—help”,或者 case$arg为 null,我会得到以下异常:

Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

$arg那么检查我的 Linux 机器中是否包含其中一个磁盘的正确方法是什么?

答案1

您似乎没有使用该命令的大部分组件。所有你需要的是:

lsblk -lnb | awk '$NF=="disk"{print $1}'

然后,为了避免在未给出参数时出现错误消息,您需要引用它,以便grep给出某物即使该内容是空字符串也要进行搜索:

if [[ "$(lsblk -lnb | awk '$NF=="disk"{print $1}' | grep -c "$arg")" != 0 ]]; then
    echo "argument is a disk"
fi

但是,当您什么都不给它时,这将返回“参数是磁盘”,因为任何内容(包括空行)都与空字符串匹配:

$ echo foo | grep -c ""
1
$ echo "" | grep -c ""
1

避免这个问题的一个简单方法,也是一个非常好的习惯,你应该总是检查你的论点的合理性——首先检查你的论点:

#!/bin/bash

if [[ -z "$1" ]]; then
  echo "The script needs at least one non-empty argument"
  exit 1
fi


arg="$1"

if [[ "$(lsblk -lnb | awk '$NF=="disk"{print $1}' | grep -c "$arg")" != 0 ]]; then
  echo "argument is a disk"
else
  echo "not a disk!"
fi

答案2

由于lsblk允许 JSON 输出,因此使用jq它来确定给定参数是否是磁盘似乎很自然:

#!/bin/sh

if lsblk -J | jq -e --arg name "$1" '.blockdevices[] | select(.type == "disk" and .name == $name)' >/dev/null
then
    printf '"%s" is a disk\n' "$1"
else
    printf '"%s" is not a disk\n' "$1"
fi

这可以正确处理脚本的第一个参数为空、缺失或无意义的情况。

-e选项jq使实用程序退出,退出状态取决于最后评估的值。例如,如果最后计算的表达式( select())为,则它将非零。null

答案3

一种可能性是有两个 if 检查。首先,检查是否可以使用$1(第一个参数)(它不为零且不是 --help),然后将其与 lsblk-Output 进行比较。例如:

#!/bin/env bash
if [[ -z "${1}" ]] || [[ "--help" == ${1} ]]; then
    echo "useful usage goes here"
else
    if [[ ` lsblk -lnb | numfmt --to=iec --field=4 | grep disk | awk '{print $1}' | grep -c ${1} ` != 0 ]]; then
        echo "argument is a disk"
    fi
fi

另一个提示:如果您对 lsblk 的输出不感兴趣,为什么要格式化它?当 lsblk 只能给你磁盘行时,你为什么要 grep 寻找“磁盘”行呢?因此,if 语句可以缩短为类似的内容(至少,如果您的 lsblk 版本知道-d):

if lsblk -dn | awk '{ print $1 }' | grep -wq $1; then

或者,甚至更短(感谢您的提示,muru(我应该更多地关注手册页......)):

if lsblk -dn -o name | grep -wq $1; then

相关内容