我如何在 if/else 语句中使用变量的 grep 结果

how can i use grep result from a variable in if/else statment

我正在尝试创建一个条件语句来检查 grep 是否发现某个软件包已安装。 如果为真,则不应安装该包,如果为假,则应安装该包。 无论我输入哪个值,我总是得到相同的结果 package is not installed 请帮忙(在我的例子中,所有软件包都已安装并且 grep 找到了匹配项。 这是代码:

chk1=$(yum list installed | grep rpmdevtools) 
chk2=$(yum list installed | grep rpmbuild)
chk3=$(yum list installed | grep rpmdev)
if [[ $chk1 -ne 0 && "$chk2" -ne 0 && "$chk3" -ne 0 ]];then
   echo "package exists"
   sleep 5
else
   echo "package doesn't exists installing .."
   sleep 5
   sudo yum install wget -y
   wget http://mirror.centos.org/centos/7/os/x86_64/Packages/rpmdevtools-8.3-5.el7.noarch.rpm
   sudo yum install rpmdevtools-8.3-5.el7.noarch.rpm -y
fi

您在这里混合了两种类型的结果:结果(即显示的文本)和 return 值。

TL;DR

可以用[[ ! -z ${chkX} ]]验证变量$chkX是否为空,如:

if [[ ! -z ${chk1} ]] && [[ ! -z ${chk2} ]] && [[ ! -z ${chk3} ]]; then
[...]

或者您可以根据退出代码执行类似的操作。

yum list installed | grep -q vim
if [[ $? -eq 0 ]]; then
  # do your stuff here when package is installed
else
  #.. do your stuff here when package isn't installed ..
fi

if yum list installed | grep -q 'vim' ;then
  # do your stuff here when package is installed
else
  # .. do your stuff here when package isn't installed ..
fi


当通过 $(yum ...) 在子 shell 中执行时,您正在存储命令回显的结果(即显示的文本)。
例如:

$> yum list installed | grep vim
vim-common.x86_64                                 2:8.2.3755-1.fc35                    @updates       

如果您想要 return 代码或退出代码,可以通过 $? 访问。
例如:

$> ls
[...]
$> echo $?
0
$> ls toto
ls: cannot access 'toto': No such file or directory
$> echo $?
2

注意每个命令都会更改退出代码。
所以访问两次$?会改变它的值。

$> ls toto
ls: cannot access 'toto': No such file or directory
$> echo $?
2
$> echo $?
0

在你的例子中,你正在测试 yum 给出的文本在数学上是否等于 0:

chk3=$(yum list installed | grep rpmdev)
if [[ $chk1 -ne 0 && "$chk2" -ne 0 && "$chk3" -ne 0 ]];then
                                             ^^^^^^

这是不可能的,因为:

  • 未找到包 -> 空变量
  • 找到一个或多个包裹 -> 包含包裹信息的单行或多行文本。
  • 而且你永远不会得到 0

如果你 运行 它与测试你有各种失败案例:

# note: rpmdevtools is not installed on by computer
$> chk1=$(yum list installed | grep rpmdevtools) 
$> test $chk1 -ne 0
bash: test: -ne: unary operator expected

# multiple vim-* packages are installed
$> chk1=$(yum list installed | grep vim) 
$> test $chk1 -ne 0
bash: test: too many arguments

我对 yum 不熟悉,可能有更好的方法来检查,但这将使你的 if 语句工作:

if
    yum list installed | grep -q rpmdevtools &&
    yum list installed | grep -q rpmbuild &&
    yum list installed | grep -q rpmdev
then

我还建议在 grep 中添加 -w,以匹配整个单词。

如果 yum list installed 是一个慢速命令,考虑将输出保存在一个变量中,然后 grepping 那个(而不是 运行 它三次):

list=$(yum list installed)

if
    echo "$list" | grep -q rpmdevtools &&
    echo "$list" | grep -q rpmbuild &&
    echo "$list" | grep -q rpmdev
then

直接的问题是 -ne 检查数字是否相等;当然 grep 的输出不会是数字 0,所以你所有的检查都失败了。

无论如何,你似乎把事情复杂化了。 yum list installed 可选择接受要检查的包列表。

if yum list installed rpmdevtools rpmbuild rpmdev >/dev/null 2>&1
then
   echo "[=10=]: package exists" >&1
else
   echo "[=10=]: package doesn't exist; installing ..." >&2
   sudo yum install -y wget
   wget http://mirror.centos.org/centos/7/os/x86_64/Packages/rpmdevtools-8.3-5.el7.noarch.rpm
   sudo yum install -y rpmdevtools-8.3-5.el7.noarch.rpm
fi

注意诊断消息的约定,包括脚本名称 [=14=] 并打印到标准错误 >&2,以及我们如何避免绝对 user-hostile 可憎的 sleep在中间。如果你想让用户有机会决定他们是否真的想继续计划的操作,显示一个单独的提示(理想情况下可以从命令行覆盖,就像 yum install -y 让你说你不'想要提示)。