我可以使用以下命令捕获 Linux 机器的磁盘设备:
\nlsblk -lnb | numfmt --to=iec --field=4 | grep disk | awk '{print $1}'\nsda\nsdb\nsdc\nsdd\n
Run Code Online (Sandbox Code Playgroud)\n在我的 bash 脚本中,我使用下面的行来测试脚本的参数是否与我的计算机上的磁盘之一匹配:
\nif [[ ` lsblk -lnb | numfmt --to=iec --field=4 | grep disk | awk '{print $1}' | grep -c $arg ` != 0 ]] \nthen\necho \xe2\x80\x9cargument is a disk\xe2\x80\x9d\n.\n.\n.\n\nfi\n
Run Code Online (Sandbox Code Playgroud)\n我运行脚本为
\nbash /tmp/verify_disks <some arg>\n
Run Code Online (Sandbox Code Playgroud)\n但如果 case$arg
被误认为arg=\xe2\x80\x9d\xe2\x80\x94help\xe2\x80\x9d
,或者 case$arg
为 null,我会得到以下异常:
Usage: grep [OPTION]... PATTERN [FILE]...\nTry 'grep --help' for more information.\n
Run Code Online (Sandbox Code Playgroud)\n那么检查$arg
我的 Linux 机器中是否包含其中一个磁盘的正确方法是什么?
您似乎没有使用该命令的大部分组件。所有你需要的是:
\nlsblk -lnb | awk '$NF=="disk"{print $1}'\n
Run Code Online (Sandbox Code Playgroud)\n然后,为了避免在未给出参数时出现错误消息,您需要引用它,以便grep
给出要搜索的内容,即使该内容是空字符串:
if [[ "$(lsblk -lnb | awk '$NF=="disk"{print $1}' | grep -c "$arg")" != 0 ]]; then\n echo "argument is a disk"\nfi\n
Run Code Online (Sandbox Code Playgroud)\nHowever, this will return "argument is a disk" when you give it nothing since anything, including an empty line, matches the empty string:
\n$ echo foo | grep -c ""\n1\n$ echo "" | grep -c ""\n1\n
Run Code Online (Sandbox Code Playgroud)\nA simple way to avoid the issue\xe2\x80\x94and also a very good habit to get into, you should always check the sanity of your arguments\xe2\x80\x94is to check your argument first:
\n#!/bin/bash\n\nif [[ -z "$1" ]]; then\n echo "The script needs at least one non-empty argument"\n exit 1\nfi\n\n\narg="$1"\n\nif [[ "$(lsblk -lnb | awk '$NF=="disk"{print $1}' | grep -c "$arg")" != 0 ]]; then\n echo "argument is a disk"\nelse\n echo "not a disk!"\nfi\n
Run Code Online (Sandbox Code Playgroud)\n
Since lsblk
allows for JSON output, it seems natural to use jq
with it to figure out whether the given argument is a disk or not:
#!/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
Run Code Online (Sandbox Code Playgroud)
This correctly handles the cases where the first argument to the script is empty, missing or nonsense.
The -e
option to jq
makes the utility exit with an exit status dependent on the last value evaluated. It will be non-zero if the last expression evaluated (the select()
) is null
, for example.
小智 5
One possibility is to have two if-checks. At first, check if you can use $1
(the first argument) (it is not zero and is not --help) and then compare it to your lsblk-Output. For example:
#!/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
Run Code Online (Sandbox Code Playgroud)
Another tip: Why are you formatting the output of lsblk if you aren't interested in it? And why are you grepping for the "disk" lines, when lsblk can give you only the disk-lines?
So the if-statement could be shortened to something like that (at least, if your version of lsblk knows -d
):
if lsblk -dn | awk '{ print $1 }' | grep -wq $1; then
Run Code Online (Sandbox Code Playgroud)
Or, even shorter (thanks for the hint, muru (I should have paid more attention to the man-page...)):
if lsblk -dn -o name | grep -wq $1; then
Run Code Online (Sandbox Code Playgroud)