tags:

views:

56

answers:

2

Hello everyone:

I am trying to analyze my agent results from a collection of 20 txt files here.

If you wonder about the background info, please go see my page, what I am doing here is just one step.

Basically I would like to take only my agent's result out of the messy context, so I've got this command for a single file:

cat run15.txt | grep -A 50 -E '^Agent Name: agent10479475' | grep -B 50 '^=='

This means : after the regex match, continue forward by 50 lines, stop, then match a line separator starts with "==", go back by 50 lines, if possible (This would certainly clash the very first line).

This approach depends on the fact that the hard-coded line number counter 50, would be just fine to get exactly one line separator.

And this would not work if I do the following code:

cat run*.txt | grep -A 50 -E '^Agent Name: agent10479475' | grep -B 50 '^=='

The output would be a mess...

My question is: how to make sure grep knows exactly when to stop going forward, and when to stop getting backward?

Any suggestion or hint is much appreciated.

Edited : I was doing something the hard way, again... The bash gurus suggest some more powerful tools. I will certainly switch to sed or awk from now on. This is my approach in the end, after trials and errors :

NUM=10479475 
for i in {1..20}; do cat "run$i.txt" | grep -A 50 -E "^Agent Name: agent_*$NUM"
| grep -B 50 '^==';done > myresults.txt
+2  A: 

You can use sed to achieve what you want:

sed -s -n -e '/^Agent Name: agent10479475/,/^==/ p' run*.txt

In this command, sed starts printing lines when it finds a line that matches the first pattern, and stops when it finds a line that matches the second pattern, treating files separately.

Ayman Hourieh
@Ayman Hourieh: thanks for this cool one liner :)
Michael Mao
+1  A: 

use awk. Its better than grep at manipulating files. I do not know what you are trying to do, so i am guessing you want to get the block that contains Agent: till the next Agent:.

awk 'BEGIN{RS="==*"}
/Agent Name: agent10479475/{
  print "-->"$0
}' file

output

$ ./shell.sh
-->
Agent Name: agent10479475
Bank Balance: $4356
Buy bids placed: 87
Desired assets --
  ticket_10960: Quantity(0),  Desired Quantity(1)
  ticket_11162: Quantity(0),  Desired Quantity(2)
  ticket_11213: Quantity(0),  Desired Quantity(1)
  ticket_11334: Quantity(0),  Desired Quantity(1)
  ticket_11425: Quantity(0),  Desired Quantity(3)
  ticket_11510: Quantity(0),  Desired Quantity(1)
  ticket_11732: Quantity(0),  Desired Quantity(2)
  ticket_11843: Quantity(1),  Desired Quantity(1)
  ticket_11904: Quantity(0),  Desired Quantity(1)
  ticket_12035: Quantity(0),  Desired Quantity(3)
  ticket_12120: Quantity(0),  Desired Quantity(1)
  ticket_12332: Quantity(0),  Desired Quantity(2)
  ticket_12433: Quantity(0),  Desired Quantity(1)
  ticket_12564: Quantity(1),  Desired Quantity(1)
  ticket_12645: Quantity(0),  Desired Quantity(3)
  flight to melbourne: Quantity(8),  Desired Quantity(8)
  room: Quantity(32),  Desired Quantity(24)
Negative quantity assets --
  ticket_7401: Quantity(-14)
  ticket_22013: Quantity(-15)
  ticket_28401: Quantity(-14)
Remaining assets --
  ticket_6463: Quantity(1)
  ticket_9861: Quantity(1)
  ticket_13441: Quantity(1)
  ticket_20813: Quantity(1)
  ticket_26853: Quantity(1)

The awk command says set the record separator (RS) to the "====" lines, so each record now contains Agent: till the next Agent: record. You can do whatever you want next using $0.

Just a side note from your home page's Perl script, you have this line

$line = s/^\s+[0-9]+//;

while iterating the file bids.txt. Are you sure you want this? This says to remove starting blanks and numbers. If its so, you won't have a number to add already. All your cat+grep+cut and the Perl script averaging function can also be combined using awk

awk 'BEGIN{
  printf "Enter agent num: "
  getline num <"-"
  regex="Agent Name: agent"num
  RS="==*"
  FS="\n"
}
$0 ~ regex{
  for(i=1;i<=NF;i++){
    if($i~/Buy bids placed:/){
       m=split($i, bids,": ")
       print bids[2]
       avgbids[num]++
       total+=bids[2]
    }
  }
}
END{
  for(i in avgbids) print i, total/avgbids[i]
}' run*txt
ghostdog74
@ghostdog74 : thanks for your answer, as always :)
Michael Mao
@ghostdog74 : well, I am really noob in bash and perl. I will go back to check the script I got. I only checked the result from my own part and that was okay, didn't make sure it still good for everyone's. Thanks for your pointing out and invaluable tips!
Michael Mao