Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

grep blocks of text out of file 1

Status
Not open for further replies.

dwcasey

MIS
Oct 31, 2002
179
US
I have a text file I've created with server info. I have a little over a hundred servers in this list. For each server, I put the data between asterisks *** so I have a file with the information shown below. What I want do now is put each block between the *** into it's own file called <servername>. Is there a way to do some sort of inclusive grep? Do I need to step up to using perl here? Sorry, I did some scripting at previous employer, got away from it, now I'm back at it, so I'm rusty.

root@server01:/usr/local/bin/getinfo
.
.
some info
.
.
root@server01:

***

root@server02:/usr/local/bin/getinfo
.
.
some info
.
.

***

root@server03:/usr/local/bin/getinfo
 
man awk

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
Something like:

Code:
gawk ' BEGIN {section=0}  {if ($0 == "***") {printf "\nSection %d located.\n",++section ; getline} ; print}'
 
PHV, the man awk was a little curt. macd68, I've tried using BEGIN and I was able to "find" my lines. I've since decided to try to insert and actual BEGIN and END or something like Server server01 BEGIN and then Server server02 END for each block and use BEGIN to grab that block, but I still can't figure out how to take that and redirect that block to a file each time I read a section.
 
A starting point:
Code:
awk '/@/{out=$1;sub(/.*@/,"",out);sub(/:.*/,"",out)}out{print>out}' /path/to/input

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
Depends on how fancy you want to get dwcasey.
This should explicate things help a little.
Code:
awk ' BEGIN {section=0}  {if ($0 == "***") {printf "\nSection %d located.\n",++section ;fname = "file" section; getline} ; printf "%s would now be going to %s using: print > fname\n",$0,fname}'
 
I found this a while back in one of the many books I have - it comes in handy and yes, it is another awk solution:

Code:
#***************************************************************************
# Check to see if there are at least 3 arguments
#***************************************************************************
if (( $# < 3 ))
  then 
    echo "Usage: $0 pattern lines file [files]"
    exit 1
fi

#***************************************************************************
# Create the internal variables
#***************************************************************************
STRING=$1
LINES=$2
shift 2     # $* now contains only file names

#***************************************************************************
# Build the awk script by reading lines from this script
#***************************************************************************
cat > a.script <<-!
     BEGIN   { output=0; }
   /$STRING/ { output=$LINES; }
             { if (output > 0) { print; output=output-1; } }
!

#***************************************************************************
# Invoke the awk script and erase it when done.
#***************************************************************************
awk -f a.script $*
rm a.script

Add a little color to your PUTTY terminal: faq52-6627
 
Guys, I'm sorry for being so dense. The solutions ya'll provided don't seem to be working and at this point, don't know enough about awk to make them work.

I've since changed the script to that the output logfile has the following:

BEGIN
my.server01.com
some data...123
some data...456
some data...blah blah
END

BEGIN
my.server02.com
some data...123
some data...456
some data...blah blah
END

I posted to usenet same question and realized that using *** was not a good idea. So I would like to have all the data between BEGIN and END put into it's own file called my.server01.com ( or preferably, a file call server01.vol01

Does this make it simpler/easier?
 
I'll still help but as a pointer in the future it might be better to just give us your unit problem and don't change the data structure or conditions.

Code:
 BEGIN {section=0} 
 {if ($0 == "***") {
     #if delimiter is found
     printf "\nSection %d located.\n",++section
     #feedback
     getline sname
     #snarf the record following the delimiter line
     match(sname,/server[0-9]+/)
     #find the server string in the line
     fname = substr(sname,RSTART,RLENGTH) ".vol0" section
     #create the destination filename by concatenation
     $0 = ""
     #set the current delimiter record output to an empty  string
     print sname > fname 
     #write the top record to create the file
 }    
 if (length($0)) {print >> fname}
 #omit the delimiter line and commit the following records
 }
 
That seems to be working great! I simply swapped the *** for just SERVER and it found everything. I'm not understanding the match(sname) line ( you probably figured that out I don't understand much ) but how difficult would be to change that? I used server01 to make it simple, but in reality, the servers only thing in common is the first bit:

home.serv01.com
home.serv0212.com
home.serv011.com

Then use this variable for fname so files are serv0212.vol1 or serv011.vol1 ( vol1 in the name needs to be vol1 always and not increment ).

Thanks for the help Mac!
 
Just replacing the string 'server' for 'serv' should work according to your description. We wouldn't worry about the section portion of the fname creation. Changed portions:

Code:
match(sname,/serv[0-9]+/)
name = substr(sname,RSTART,RLENGTH) ".vol1"

Thanks for the positive feedback.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top