Script Help/Advice

Alright, I feel like I have a pretty good basic knowledge of shell scripting, but this one is throwing me for a loop. I know I've seen something similar done with awk, but I couldn't find it with the search function.

I've grepped through my log file and get results like this:

--
/home/dir1/file-egress-filter-Remark : Stuff
/home/dir1/file-egress-filter-permit stuff
/home/dir1/file-egress-filter-permit other stuff
/home/dir1/file-egress-filter:permit more stuff
--
/home/dir1/other-egress-filter-Remark : Other
/home/dir1/other-egress-filter-permit other
/home/dir1/other-egress-filter-permit other others
/home/dir1/other-egress-filter:permit more other
--

This can continue on for few or many files. Notice that the last line of each has a colon (:slight_smile: as the last delimiter where as the others are a dash (-) and also that there is a : in the first line of each.

I want output like:

--
file-egress-filter
Remark : Stuff
permit stuff
permit other stuff
permit more stuff
--
other-egress-filter
Remark : Other
permit other
permit other others
permit more other
--

So, the stuff between each set of -- changes and I want to take the file name and use it as a header and then just print the stuff after the delimiter which is a dash for all but the last line.

Ideas?

sed sounds like an appropriate tool to split the lines up into their components.

not extremely elegant, but... you could probably improve the logic/flags:

nawk -f earnstaf.awk myGreppedLogFile
earnstaf,awk:

BEGIN {
  FS="[/]"
}
/^--/ {block++;print;next}
block {
  match($NF, "^.*-.*-[^-][^-]*-")
  printf("%s\n", substr($NF, 1, RLENGTH-1))
}
{
  !(block) && ($0 ~ ":") ? match($NF, ":[^:][^:]*$") : match($NF, "-[^-][^-]*$")
  printf("%s\n", substr($NF, RSTART+1))
  block=0
}

This is a snippet of code.

Try this Out!!!!!!!!!!!!!!!!!!!!!!!

sed '1s/\(.*\)\(file.*filter\)\(.*\)/\2/' filename |sed '2,4d'

cut -d'/' -f4 filename | sed 's/\(.*\)\(permit.\)/\2/' |sed 's/\(.*\)\(Remark.\)/\2/'

Regards,
aajan

vgersh, that looks pretty nice even though I can decipher very little of the actual awk code. It also works well with a couple of issues which are my fault for failing to include them in the example.

1.) The grep returns some "blank" lines, staying with my example they look like this:

--
/home/dir1/file-egress-filter-Remark : Stuff
/home/dir1/file-egress-filter-permit stuff
/home/dir1/file-egress-filter-
/home/dir1/file-egress-filter-permit other stuff
/home/dir1/file-egress-filter-
/home/dir1/file-egress-filter:permit more stuff
--
/home/dir1/other-egress-filter-
/home/dir1/other-egress-filter-Remark : Other
/home/dir1/other-egress-filter-permit other
/home/dir1/other-egress-filter-
/home/dir1/other-egress-filter-permit other others
/home/dir1/other-egress-filter:permit more other
--

The code is returning those as just the filename ie "other-egress-filter-" and I would like to return it as a truly blank line (under the header) Thoughts?

2.) Disregard 2 :slight_smile: ... I was able to pipe information from the grep into the awk.

I read up on what you were doing with match and RLENGTH and RSTART, but I'm having a little trouble wrapping my head around the code itself.

Bear with me as I try to go through this:

BEGIN {
  FS="[/]"  #setting the FS to / .. I assume for the /home/dir1/ part of my pattern space..                                         
}
/^--/ {block++;print;next}  #look for -- at the start of line.  Unsure of the significance of incrementing the block... print the -- and move to the next line 
block {
  match($NF, "^.*-.*-[^-][^-]*-")  #regexp matching the "file" portion of my pattern (file-egress-filter-) .. not sure on the exclusion of dashes ([^-])..
  printf("%s\n", substr($NF, 1, RLENGTH-1)) #print newline, then print the line, starting at the first position and the whole string minus the last character.
}
{
  !(block) && ($0 ~ ":") ? match($NF, ":[^:][^:]*$") : match($NF, "-[^-][^-]*$") #if the line was not matched on the previous regexp (block) and contains a : then match on a : then no colon until the end of the line?
  printf("%s\n", substr($NF, RSTART+1)) #kinda lost here... is it saying print 1 position after the match? ..so after the :?
  block=0  #once again, not sure on the significance of the count. 
}

So, I realize that probably way off... I'll play more with awk.

BEGIN {
  FS="[/]"
}
/^--/ {block++;print;next}
block {
  match($NF, "^.*-.*-[^-][^-]*-")
  printf("%s\n", substr($NF, 1, RLENGTH-1))
}
!match($NF, "-[^-][^-]*$") {print "";next }
{
  !(block) && ($0 ~ ":") ? match($NF, ":[^:][^:]*$") : match($NF, "-[^-][^-]*$")
  printf("%s\n", substr($NF, RSTART+1))
  block=0
}

 awk '/ :/{printf "%s-%s-%s\n%s:%s\n",$4,$5,$6,$7,$8;next}
/--/{print;next}
{FS="[-/:]";print $7}'  FS="[-/:]"
% cat file
--
/home/dir1/file-egress-filter-Remark : Stuff
/home/dir1/file-egress-filter-permit stuff
/home/dir1/file-egress-filter-permit other stuff
/home/dir1/file-egress-filter:permit more stuff
--
/home/dir1/other-egress-filter-Remark : Other
/home/dir1/other-egress-filter-permit other
/home/dir1/other-egress-filter-permit other others
/home/dir1/other-egress-filter:permit more other
--
% awk '/ :/{printf "%s-%s-%s\n%s:%s\n",$4,$5,$6,$7,$8;next}
/--/{print;next}
{FS="[-/:]";print $7}'  FS="[-/:]" file
--
file-egress-filter
Remark : Stuff
permit stuff
permit other stuff
permit more stuff
--
other-egress-filter
Remark : Other
permit other
permit other others
permit more other
--

Use nawk or /usr/xpg4/bin/awk on Solaris.

radoulov,
given a sample input with 'blanks'

--
/home/dir1/file-egress-filter-Remark : Stuff
/home/dir1/file-egress-filter-permit stuff
/home/dir1/file-egress-filter-
/home/dir1/file-egress-filter-permit other stuff
/home/dir1/file-egress-filter-
/home/dir1/file-egress-filter:permit more stuff
--
/home/dir1/other-egress-filter-
/home/dir1/other-egress-filter-Remark : Other
/home/dir1/other-egress-filter-permit other
/home/dir1/other-egress-filter-
/home/dir1/other-egress-filter-permit other others
/home/dir1/other-egress-filter:permit more other
--

the output is:

--
file-egress-filter
Remark : Stuff
permit stuff

permit other stuff

permit more stuff
--

other-egress-filter
Remark : Other
permit other

permit other others
permit more other
--

the 'header' in the SECOND block is AFTER the first blank line - while I believe it should be first.
I like the solution, but don't really like explicitely referencing field numbers - kinda ties you up to a particular number and the 'depths' of the patterns/paths - I believe using 'match' and regex makes it more 'generic'.

Yes,
I agree, more explicit referencing -> less flexible code.
I would only suggest an approach like mine for fixed formats.

Thanks for the replies guys... good stuff to learn.

Seems to be an issue in processing this line:

/home/dir1/file-egress-filter-Remark : Stuff

It's removing the word Remark and just printing everything after the : so the output is

 Stuff

when it should be:

Remark : Stuff

everything is kosher here - no 'drops' given the sample file with 'blanks'.
Paste your sample file once again.

Each block will follow a format similar to this:

--
/home/dir1/file-egress-filter-Remark : Stuff
/home/dir1/file-egress-filter-permit stuff
/home/dir1/file-egress-filter-
/home/dir1/file-egress-filter-Remark : Other Stuff
/home/dir1/file-egress-filter:permit other stuff
--

I guess the things to consider are that the filename is delimited from the text with a - on all but the last line in which case it's a :. Also, lines within the block can contain a : on more than one occasion and need to be retained. Then also, the "blank" line issue where it lists just the file name.

On the above example we would want:

file-egress-filter
Remark : Stuff
permit stuff

Remark : Other Stuff
permit other stuff

Thanks again for your help...

Assuming that the 'something:other' is to be treated differently than 'something : other'

BEGIN {
  FS="[/]"
}
/^--/ {block++;print;next}
block {
  match($NF, "^.*-.*-[^-][^-]*-")
  printf("%s\n", substr($NF, 1, RLENGTH-1))
}
!match($NF, "-[^-][^-]*$") {print "";next }
{
  ($0 ~ "[^ ]:[^ ]") ? match($NF, ":[^:][^:]*$") :  match($NF, "-[^-][^-]*$")
  printf("%s\n", substr($NF, RSTART+1))
  block=0
}

Works like a charm ... thanks.