1

I have next script

./students.sh |awk '{print $1,$4}'
CLARA
MARC [Found]
STEVE [Found]
GREG [FOUND]
JAKE
#IF FOUND PEFORM ->
./students.sh -move  

And i need to create a condition in which -move flag will be applied only in condition when MARC STEVE AND GREG will have status FOUND, in other case just dont do nothing.

Kwaker
  • 45
  • 9

1 Answers1

1

One way to do this type of generic task is to use the exit code of a previous program to determine whether or not to execute the next program.

Generically:

if anycommand; then
    anothercommand 
fi

anothercommand will only execute if anycommand was successful, as determined by the exit code for anycommand.

awk can exit with non-zero status if you want it to. As a simple example:

/MARC/ {
    # Successful exit immediately if MARC is found
    exit 0
}
/CRAM/ {
    # Failure exit immediately if CRAM is found
    exit 1
}

Your task then becomes writing the awk code to exit 0 if MARC STEVE and GREG are all found, and exit 1 otherwise. 0 is the default exit code, so make sure you explicitly exit 1 if they are not all present.

if ./students.sh | awk 'your code here'; then
    ./students.sh -move  
fi

You can also "short circuit" this. The two ampersands tells the shell to only execute ./students -move if the previous command exited with status 0.

./students.sh | awk 'your code here' && ./students.sh -move

EDIT: When Charles Duffy comments, you should definitely pay attention. Please read through the post he linked to in the comments. Here is an example of how you can organize your awk code. As written it is case-sensitive, so "MARC [FOUND]" would not trigger success. Also, there are no anchors, so "ARAMARC [Found]" would trigger success, not just "MARC [Found]". You'll have to beef up the code to handle these situations, but hopefully this helps.

/MARC \[Found\]/ {
    # Set flag to true
    marc = 1
}
/STEVE \[Found\]/ {
    steve = 1
}
/GREG \[Found\]/ {
    greg = 1
}
END {
    if (marc && steve && greg) {
        # Successful exit if all 3 are found
        exit 0
    }
    # Failure exit otherwise
    exit 1
}

EDIT 2: You might have noticed the above solution doesn't scale very well. For checking three students, it isn't bad. But if you want to check that 10,000 students are "Found" the solution is untenable. If you are looking for a solution that scales well, I would look into creating a sorted file called "required.dat" that contains the students that need to be Found. As you run your ./students.sh script, pipe it to awk '$4 ~ /\[Found\]/ {print $1}' | sort > found.dat. This will create another file with the students which are found. Then run N_REQ_NOT_FOUND=$(comm -23 required.dat found.dat | wc -l) to find the number of students that were required but not found. If $N_REQ_NOT_FOUND is larger than 0, it means some students were required but not found.

Rusty Lemur
  • 1,697
  • 1
  • 21
  • 54
  • 1
    [Why is testing `$?` to see if a command succeeded or not an antipattern?](https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) – Charles Duffy Feb 11 '20 at 15:26
  • ...and the OP wants to test stdout for two separate patterns on two separate lines. One can absolutely do that with `awk`, but this answer doesn't currently show how. – Charles Duffy Feb 11 '20 at 15:28
  • 1
    `Generically: anycommand if [[ $? == 0 ]]; then` - I would disagree - generically `if anycommand; then` – KamilCuk Feb 11 '20 at 18:03
  • You're right KamilCuk, and the answer has been updated. – Rusty Lemur Feb 11 '20 at 18:22