简体   繁体   中英

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

i am trying to create a condition statement that checks if the grep found if a package is installed. if it is true, then the package should not be installed, and if it is false, then the package should be installed. i am always getting the same result package is not installed no matter which value i put please help (in my case the all packages are installed and grep finds a match. here is code:

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

You're mixing 2 types of results here: result (ie displayed text) and return value.

TL;DR

You can verify if the variable $chkX is not empty with [[ ! -z ${chkX} ]] [[ ! -z ${chkX} ]] , such as:

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

Or you can do something like this, based on exit codes.

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

or

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


When executing in a subshell through $(yum...) you are storing the result (ie displayed text) that's echoed by the command.
For instance:

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

If you want the return code or exit code, it's accessible through $? .
For example:

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

Note every command changes the exit code.
So accessing twice $? will change its value.

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

In your case, you're testing if the text given by yum is mathematically equal to 0:

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

It's not possible because:

  • no package found -> empty variable
  • one or many package found -> single or multiline text with package information.
  • and you'll never get 0 .

If you run it with test you have various cases of failure:

# 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

I'm not familiar with yum, there may be a better way to check, but this will make your if statement work:

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

I also recommend adding -w to grep, to match a whole word.

If yum list installed is a slow command, consider saving the output in a variable, and grepping that (instead of running it three times):

list=$(yum list installed)

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

The immediate problem is that -ne checks for numeric equality; of course the output from grep is not going to be the number 0, so all of your checks fail.

You seem to be overcomplicating things significantly anyway. yum list installed optionally accepts a list of packages to check.

if yum list installed rpmdevtools rpmbuild rpmdev >/dev/null 2>&1
then
   echo "$0: package exists" >&1
else
   echo "$0: 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

Notice the convention for diagnostic messages to include the script name $0 and print to standard error >&2 , and how we avoid the absolutely user-hostile abomination of sleep ing in the middle. If you want to give users a chance to decide whether they really want to do that, display a separate prompt (and ideally make it possible to override from the command line, just like yum install -y lets you say you don't want a prompt).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM