1

"Issue"... The command is doing what is actually instructed to.

Given this mbox format file:

From: me@my.dom #identifies the beginning of the first mail    
...
Subject: crcheck.sh #identifies the beginning of the mail body
...
MYVARIABLE="123"
...
From: me@my.dom #identifies the beginning of the next mail
...
Subject: crcheck.sh #identifies the beginning of the mail body
...
From: another@evil.dom #identifies the beginning of next mail
...
Subject: crcheck.sh #identifies the beginning of the mail body
EVILVARIABLE="0.00" #just to mention a value that would cause division by zero errors and crash my main script.
...
From: me@my.dom #identifies the beginning of the next mail
...

I need to select all lines between a valid Subject: and the next From:, but the From: preceiding the Subject line should be the $GOODSENDER one.

The code I'm running:

GOODSUBJECT="crcheck.sh"
GOODSENDER="me@my.dom"
cat $MBOX |awk "/Subject\: $GOODSUBJECT$/{a=1}/From\:\ $GOODSENDER /{print;a=0}a"|grep $i\=\"

Outputs:

MYVARIABLE="123"
EVILVARIABLE="0.00"

Expected output:

MYVARIABLE="123"

The command is doing what it's instructed to, as those lines are acutally between two of the lines I set as patterns for awk.

But how can I adjust it to have this desidered behaviour?

  • I don't see "crcheck.sh" subject in your input. Will you update the input? – RomanPerekhrest Sep 15 '17 at 19:24
  • TY for your attention, it's everywhere. I edited the question. – Marco Sep 15 '17 at 19:27
  • some kind of duplicate stackoverflow.com/questions/46245806/… – RomanPerekhrest Sep 15 '17 at 19:56
  • TY sir, the other post on SO turned into a best practice coding contest, and it was probably my fault, because the question was all about this single awk line. I'm going to delete the SO one, as soon as the guy telling me that the error was all about my bad coding practices will reply. :) – Marco Sep 15 '17 at 20:01
2

Try:

$ awk "/Subject:/{a=0} /From:/{a=0; b=0} a && b && /MYVARIABLE=/{print} /Subject: crcheck.sh$/{a=1} /From: me@my.dom/{b=1}" mbox
MYVARIABLE="123"

How it works

  • /Subject:/{a=0} /From:/{a=0; b=0}

    When we reach a subject or from line, turn all flags false.

  • a && b && /MYVARIABLE=/{print}

    If both flags are true and the line includes the string MYVARIABLE=, then print the line.

  • /Subject: crcheck.sh$/{a=1}

    If the subject line is good, set flag a to true.

  • /From: me@my.dom/{b=1}

    If the from line is good, set flag b to true.

Notes

  1. It is poor practice to use all caps for shell variables. The system use all caps for its variables and you don't want to accidentally overwrite one of them.

  2. cat is unneeded. Awk takes file names as arguments.

  3. In regexes, : and space are not special. They don't need to be escaped.

  4. In email headers, Subject: and From: are both supposed to start at the beginning of the line. A better regex for each might be /^Subject:/ and /^From:/ where ^ is the regex symbol for start-of-line.

Passing a variable to awk

$ var=MYVARIABLE
$ awk -v x="$var" '/Subject:/{a=0} /From:/{a=0; b=0} a && b && $0 ~ (x"="){print} /Subject: crcheck.sh$/{a=1} /From: me@my.dom/{b=1}' mbox
MYVARIABLE="123"

Sample Input

The output above was generated using this as the input file:

$ cat mbox
From: me@my.dom
...
Subject: crcheck.sh
...
MYVARIABLE="123"
...
From: me@my.dom
...
Subject: crcheck.sh
...
From: another@evil.dom
...
Subject: crcheck.sh
EVILVARIABLE="0.00"
...
From: me@my.dom
...

This is the same as in the question except that, to restore it to mbox format, the added comments have been removed.

  • this won't print anything on the OP's input: ibb.co/fXxSPQ – RomanPerekhrest Sep 15 '17 at 19:54
  • @RomanPerekhrest The OP's "input" has comments. From the question, it was clear that the comments weren't in the input he was testing with. So, I removed the comments. With comments removed, the code produces for me exactly the output that I show. I will update the answer showing the input I use. – John1024 Sep 15 '17 at 19:57
  • there's no output for me too! user@host:~$ cat /var/mail/user |awk "/Subject:/{a=0} /From:/{a=0; b=0} a && b{print} /Subject\: $/{a=1} /From: me@my.dom/{b=1}" user@host:~$ – Marco Sep 15 '17 at 20:36
  • 1
    @Marco OK. There are two reasons for that. (1) The code that you are testing is different from my code. Your code includes the command /Subject\: $/{a=1} which will only trigger if the subject line consists of a single space. This likely never happened in your file. (2) I can't debug the output from your /var/mail/user file since I don't know what is in it. While we are debugging, please use the sample input from the question (but with the comments removed as shown in my answer). Thanks. – John1024 Sep 15 '17 at 20:43
  • 1
    TY very much for your extra hints, too! – Marco Sep 16 '17 at 6:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.