excluding following line with grep

44 views
Skip to first unread message

Don Delp

unread,
Aug 3, 2009, 3:17:16 PM8/3/09
to nlug...@googlegroups.com
I have a report log where each entry spans two lines. Visually you
can deal with it, but it's not super nice to grep. I'm using GNU
grep 2.5.3 .

The format looks like this:
serial user status lastlogin
-->token startdate expdate


For instance, I might have this section of log:


1234 JonDoe Enabled 1/2/3
-->token 1/1/1 3/3/3

1235 Unassigned 0/0/0
-->token 0/0/0 0/0/0

1236 Disabled 1/2/3
-->token 1/1/1 2/2/3

I know that I can grab just the active users with "grep -A1 Enabled",
but what if I want to exclude tokens that are Unassigned, but keep any
other statuses? I would think that "grep -v -A1 Unassigned" would
discard the line with Unassigned and expand the selection to the next
line, but I get everything.

I've been using this command to test the concept: echo -e "a\nb\nc\nd"
|grep -v -A1 b

I would expect that command to return just "a" and "d" but I get "b"
and "c" as well.

Is there a way to do this with grep, or am I trying to hammer a screw?
Would a clever RegEx fix my problem, or should I think about writing
a script to process this log?

Thanks.

Brandon Valentine

unread,
Aug 3, 2009, 5:20:58 PM8/3/09
to nlug...@googlegroups.com
I'd use sed(1):

sed -ne '/Unassigned/{N;p;}' mylogfile.txt

Hope this helps,

Brandon
--
Brandon D. Valentine
http://www.brandonvalentine.com

Don Delp

unread,
Aug 3, 2009, 10:34:21 PM8/3/09
to nlug...@googlegroups.com
On Mon, Aug 3, 2009 at 4:20 PM, Brandon
Valentine<bra...@brandonvalentine.com> wrote:
> I'd use sed(1):
> sed -ne '/Unassigned/{N;p;}' mylogfile.txt
> Hope this helps,
> Brandon
> On Mon, Aug 3, 2009 at 2:17 PM, Don Delp <nesm...@gmail.com> wrote:

Brandon,
You gave me what I needed to figure it out. Thanks!

I don't often use sed other than with simple find/replace. I checked
the man page and tweaked the options to this:
sed -e '/Unassigned/{N;d;}' token.rpt

Removing the -n stopped it from suppressing the non-matching output.
Adding the d into the script causes it to delete the selected lines.
The p prints current pattern space, so I removed it.

Running your command actually outputs just the lines that I wanted to
get rid of. wc -l says there are 88 of them. All I had to do after
that was tweak the script until my output was 88 less than my
original.

Thanks again.

Don Delp

unread,
Aug 4, 2009, 7:50:24 AM8/4/09
to nlug...@googlegroups.com
On Mon, Aug 3, 2009 at 9:34 PM, Don Delp<nesm...@gmail.com> wrote:
> On Mon, Aug 3, 2009 at 4:20 PM, Brandon
> Valentine<bra...@brandonvalentine.com> wrote:
>> I'd use sed(1):
>> sed -ne '/Unassigned/{N;p;}' mylogfile.txt
>> Hope this helps,
>> Brandon
>> On Mon, Aug 3, 2009 at 2:17 PM, Don Delp <nesm...@gmail.com> wrote:
>
> Brandon,
> You gave me what I needed to figure it out.  Thanks!
>
> I don't often use sed other than with simple find/replace.  I checked
> the man page and tweaked the options to this:
> sed -e '/Unassigned/{N;d;}' token.rpt
>
> Removing the -n stopped it from suppressing the non-matching output.
> Adding the d into  the script causes it to delete the selected lines.
> The p prints current pattern space, so I removed it.
>
> Running your command actually outputs just the lines that I wanted to
> get rid of.  wc -l says there are 88 of them.  All I had to do after
> that was tweak the script until my output was 88 less than my
> original.
>
> Thanks again.
>

Another option (using sed) hit me in the shower. In my case, each row
has a newline followed by "-->" before the rest of the data for that
user. I can use sed to replace '\n-->' with ' ' and have all my data
in one row per entry. From there, I can grep it the way I expect to
and then use cut to just get the fields I want.

I'm going to ask my windows-using coworkers what options they have to
manage data like this. I expect to hear: "Get the new guy to do it
manually in notepad." :)

Steven S. Critchfield

unread,
Aug 4, 2009, 8:03:12 AM8/4/09
to nlug...@googlegroups.com
----- "Don Delp" <nesm...@gmail.com> wrote:
> Another option (using sed) hit me in the shower. In my case, each
> row
> has a newline followed by "-->" before the rest of the data for that
> user. I can use sed to replace '\n-->' with ' ' and have all my data
> in one row per entry. From there, I can grep it the way I expect to
> and then use cut to just get the fields I want.
>
> I'm going to ask my windows-using coworkers what options they have to
> manage data like this. I expect to hear: "Get the new guy to do it
> manually in notepad." :)

Using cut is eeww. Try awk.

sed 's/\n-->/ /' <in_log |grep -v 'username to be rid of' | awk '{print $2}'

Using awk will split on whitespace normally. Then you just need to know what
column number you want to print. Granted it won't work well if you have
conditional columns that occasionally don't have content, or fields with
allowable spaces in them.

--
Steven Critchfield cri...@basesys.com

Don Delp

unread,
Aug 4, 2009, 10:26:02 AM8/4/09
to nlug...@googlegroups.com
Some of the entries have 2 word users, others have 3 word users. If
you want to see "eww", this is what I ended up running:
cat token.rpt |grep -v Unassigned |cut -f2- -d' ' | rev | awk '{print
$2,$8,$10,$11,$12}' | rev > expiring.txt

I wasn't sure how to get awk to give me everything after a certain
point, so I used cut to get the second field and all following fields,
then reversed it since the name field was the only variable length
field. Used awk to grab the dates and the names in reverse, then
flipped it back.

I had to do a little more cleanup to make it presentable, like finding
out that ^@ in vim is a null char and that to type it I needed to hit
"ctrl+v 000"

Whew, that was fun. :)
Reply all
Reply to author
Forward
0 new messages