Failure: if grep "$Var" "$line" inside while read line loop

Hi everybody,

I am new at Unix/Bourne shell scripting and with my youngest experiences, I will not become very old with it :o

My code:

#!/bin/sh

set -e
set -u

export IFS=

optl="Optl"
LOCSTORCLI="/opt/lsi/storcli/storcli"

($LOCSTORCLI /c0 /vall show | grep RAID | cut -d " " -f-5 | sed 's/   / /1') > /opt/lsi/storcli/output.txt

 while read line
 do
    echo "$line" > /opt/lsi/storcli/templine.txt                  #only to test "grep" in "if" with a file
    if grep -qv "$optl" "$line"                                   # Testfile-Location /opt/lsi/storcli/templine.txt;   
        then
            fehler="Failure on: Controller 0"
        else
            fehler="1"
    fi
 done < "/opt/lsi/storcli/output.txt"

Some background information

content of output.txt

0/0 RAID1 Optl              <-- as seen in Notepad++ there are CR and LF "signs at the end of the line, maybe this information is important
1/1 RAID1 Optl                <-- as seen in Notepad++ there are CR and LF "signs at the end of the line
 

content of templine.txt at the first time of the while-loop:

0/0 RAID1 Optl

content of templine.txt at the second time of the while-loop:

1/1 RAID1 Optl

My Problem with the code

"if grep -qv "$optl" "$line" 

doesn't work --> Error messages: "grep: 0/0 RAID1 Optl: No such file or directory" and "grep: 1/1 RAID1 Optl: No such file or directory"
[/CODE]
BUT

"if grep -qv "$optl" /opt/lsi/storcli/templine.txt 

works as expected. But I would prefer to work with the $line-variable.

What did I wrong. Where is the/my mistake? I spend the last 3 nights for this simple code and did a lot of google research :frowning:

Than you very much for support!!!

Sorry, but you set yourself up for that: it usually works as soon as you do it right. ;-))

Seriously: grep expects its arguments in the form (i simplify to the relevant here): grep <pattern> <file> . What you fed it instead, though, is: grep <pattern> <variable, that is: string which to search for pattern> . This is why grep treated the string you wanted to be searched as a filename - and of course this filename is not found, which is why you got the error of "file not found".

There is in fact another form of grep -invocation, where you can feed grep something from <stdin> , like this:

some_process | grep <pattern>

To get your string there is possible but you first have to create a process with the string as output. Can you guess which process that could be?

Yes, of course: echo "$variable" . Therefore, here is your solution:

echo "$variable" | grep <pattern>

Picture grep as a machinery which has two different intakes: a file or <stdin> . Just like a coffee machine might have two intakes, one for ground coffee and one for whole beans. Which one is selected depends on how it is invoked. But you cannot pour your data into the wrong intake and then expect grep to do it right: put your beans into the opening for ground coffee and the coffee machine will make all sorts of things but probably not coffee.

I hope this helps.

bakunin

PS: CR/LF line endings are indeed important and will confuse a lot of UNIX utilities. I suggest to correct them to UNIX newlines first thing. There are unix2dos and dos2unix , two utilities which change back and forth from/to UNIX-style line breaks from/to DOS-style line breaks, sed -scripts and many other ways of achieving the same.

PPS: you do not need to create a temporary file at all in your code: as i have shown you you can directly work with the variable content.

1 Like

Welcome to the forum.

The command structure is

grep -options pattern file

That means the $line variable needs to hold a filename which it obviously doesn't. You could " grep " (pls. note the quotes - there may be better ways to check) a variable's contents like

echo $var | grep pattern

.

1 Like

I salute to Bakunin and RudiC :b::b::b:

echo "$variable" | grep <pattern>

works perfect! :slight_smile:

Thank you so much for the solution. A solution I never would have found by myself. :o

Bankunin, its to early in the morning in Germany, so I only could test with $line and grep. Later on this weekend I will test the same solution with the temporary file.

Often shell-builtins are the better alternative.

  case "$line" in
  *"$optl"*)
    fehler="1"
  ;;
  *)
    fehler="Failure on: Controller 0"
  ;;
  esac

Bankunin, now I have corrected the code, so that I also don't need a file anymore. Thanks again for your support!

Subsonic