Operating System - HP-UX
1759755 Members
3543 Online
108888 Solutions
New Discussion юеВ

Re: awk multiline record print

 
SOLVED
Go to solution
Yashy
Occasional Advisor

awk multiline record print

Hi,
I have a multiline text file like below:

dn:djkjdf jdkjkjf
homedir kkjkjk
shell dkjkfjkgjg
userpasswd kkjk

dn:djkjdf jdkjkjf
homedir kkjkjk
shell dkjkfjkgjg
userpasswd kkjk

The file has hundreds of 4-line blocks like above. What I want is to output each 4-line block to each different file. If it is a four-line-record I want to print each record to a different file.

Please advise.
Thanks

9 REPLIES 9
Sandman!
Honored Contributor

Re: awk multiline record print

Yashy,

Here's a simple awk script inside a for loop that you can use to separate each of the 4-line blocks into separate output streams.

# for i in ; do
> awk 'BEGIN{FS=""} {print $0 > "block"NR".out"}' $i
> done
Sandman!
Honored Contributor

Re: awk multiline record print

Typo in the last posting. Change the "FS" to "RS" in the "BEGIN" section of the awk construct i.e.

# for i in ; do
> awk 'BEGIN{RS=""} {print $0 > "block"NR".out"}' $i
> done
Hein van den Heuvel
Honored Contributor
Solution

Re: awk multiline record print


In a 'one-liner':

awk '/^dn/{n=NR;dn=$0;h=s=""}/^home/{h=$0}/^she/{s=$0}/^user/&&(NR-n==3){i++; f="xx_" i ".tmp"; print dn "\n" h "\n" s "\n" $0 > f }' < x

In a script use:
/^dn/{n=NR;dn=$0;h=s=""}
/^home/{h=$0}
/^shel/{s=$0}
/^user/&&(NR-n==3){
i++;
f="xx_" i ".tmp";
print dn "\n" h "\n" s "\n" $0 > f
}

What happens?
- If we see a line starting with dn then remember the line number, remember the line in dn, clear home and shell variables.
- Remember home and shell in h and s if you see them
- If you see a line starting with user, and it is 3 lines after dn, then
-- increment the file number
-- generate a fresh file name
-- print all four line onto the new file name

Hein.




Sandman!
Honored Contributor

Re: awk multiline record print

If all these 4-line blocks are in a single file then you don't need the "for" loop.

Use the awk construct within a for loop only if you want to operate on multiple files within a directory. Otherwise the awk statement by itself will do what you want:

# awk 'BEGIN{RS=""} {print $0 > "block"NR".out"}'

cheers!!!
Hein van den Heuvel
Honored Contributor

Re: awk multiline record print


"If it is a four-line-record"

This is critical. How do you define that.
My first solution is a fairly rigirous test, only creating a new file under specific conditions.

If dor example you 'know' that there will always be a four-line-record as soon as you see a line starting with 'dn:' then the solution simplyfies a lot. For example:


awk '/^dn:/{x=4;i++;f="xx_"i".tmp"; while (x--) {print $0>f; getline} }' < x


hth,
Hein.
Yashy
Occasional Advisor

Re: awk multiline record print

Thanks. It is working can you please explain more about the variable and the interpolation of them.

yashy
Muthukumar_5
Honored Contributor

Re: awk multiline record print

To explain this,

# awk '/^dn:/{x=4;i++;f="xx_"i".tmp"; while (x--) {print $0>f; getline} }' < x

a) It will read from a file called x
b) awk will search a line with dn string
c) It will collect 4 lines from the line starting with dn:
d) New file name is assigned as, xx_1.tmp 1 will be increased with i variable. This file is assigned to f variable.
e) print $0 > f will write as, print $0 > xx_1.tmp

File name will be varied with 1..n.

hth.
Easy to suggest when don't know about the problem!
Leif Halvarsson_2
Honored Contributor

Re: awk multiline record print

Hi,
Are there empty lines in the file ? If not, why not use split -l 4 (split a file into 4-lines pieces).

If there are empty lines, supress those lines (there is several ways to do that) and then use split.

If it not is possible to just to supress lines, use a simple script as:

awk '/^dn/ {print $0; getline; print $0; getline; print $0; getline; print $0;}' file >outfile

and, then use split -l 4 on outfile.
Yashy
Occasional Advisor

Re: awk multiline record print

Thanks everyone. It works well.
Thanks Leif. I already know about the split option and I was actually looking for an awk option. Thanks again everyone.

Yashy