0

I'm trying to parse lines from an error log in BASH and then send a certain part out to a BASH variable to be used later in the script and having issues once I try and pass it to a BASH variable.

What the log file looks like:

1446851818|1446851808.1795|12|NONE|DID|8001234

I need the number in the third set (in this case, the number is 12) of the line

Here's an example of the command I'm running:

tail -n5 /var/log/asterisk/queue_log | grep 'CONNECT' | awk -F '[|]' '{print $3}'

The line of code is trying to accomplish this:

  1. Grab the last lines of the log file
  2. Search for a phrase (in this case connect, I'm using the same command to trigger different items)
  3. Separate the number in the third set of the line out so it can be used elsewhere

If I run the above full command, it runs successfully like so:

tail -n5 /var/log/asterisk/queue_log | grep 'CONNECT' | awk -F '[|]' '{print $3}'
12

Now if I try and assign it to a variable in the same line/command, I'm unable to have it echo back the variable.

My command when assigning to a variable looks like:

tail -n5 /var/log/asterisk/queue_log | grep 'CONNECT' | brand=$(awk -F '[|]' '{print $3}')

(It is being run in the same script as the echo command so the variable should be fine, test script looks like:

#!/bin/bash
tail -n5 /var/log/asterisk/queue_log | grep 'CONNECT' | brand=$(awk -F '[|]' '{print $3}')
echo "$brand";

I'm aware this is most likely not the most efficient/eloquent solution to do this, so if there are other ideas/ways to accomplish this I'm open to them as well (my BASH skills are basic but improving)

2
  • 3
    Not foo | x=$(bar), instead x=$(foo | bar). Commented Nov 9, 2015 at 1:23
  • The right side of a pipe runs in a subshell, so changes made there are lost when that side of the pipeline exits: x=hello; echo good-bye | read x; echo $x will output hello, not good-bye. Commented Nov 9, 2015 at 1:34

1 Answer 1

6

You need to capture the output of the entire pipeline, not just the final section of it:

brand=$(tail -n5 /var/log/asterisk/queue_log | grep 'CONNECT' | awk -F '|' '{print $3}')

You may also want to consider what will happen if there is more than one line containing CONNECT in the final five lines of the file (or indeed, if there are none). That's going to cause brand to have multiple (or no) values.


If your intent is to get the third field from the latest line in the file containing CONNECT, awk can pretty much handle the entire thing without needing tail or grep:

brand=$(awk -F '|' '/CONNECT/ {latest = $3} END {print latest}')
Sign up to request clarification or add additional context in comments.

4 Comments

right and also lose the grep: tail ... | awk -F '|' '/CONNECT/{print $3}'
@Ed, I thought about that but the messiness of only looking at the last five lines paused me. However, I've added a suggestion as per your comment, indicating the slight difference from what the OP asked for which, of course, is not always what they want :-)
Re: number of lines in the search, my live copy has it set to -n1 as it uses inotifywait and checks the file the instant it's modified, I was running this by hand and the last log entry with the applicable phrase was about 4 lines up so I just modified it quickly for testing/running by hand.
@paxdiablo I wasn't suggesting getting rid of the tail, just the grep. I'm really not sure what the OP will want if CONNECT appears multiple times in the last 5 lines (first? last? all?)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.