For Programmers: Free Programming Magazines  


Home > Archive > AWK > July 2006 > Inserting Text into a file









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Inserting Text into a file
ianbacon999@hotmail.com

2006-07-19, 7:56 am

Hi, I need help inserting text into a file.

Here's what I have so far

#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage:$0 insert "
exit
fi

JMS_INSERTFILE=$1

cat jms.bak | nawk -v filename=$JMS_INSERTFILE '
BEGIN{if (filename=="")
{
print "Error:no filename given";
exit 1;
}
}
!/\<\/queue\>/ {print}
/\/\>/ {while( getline<filename) print;}
' > jms.xml

but this inserts after the first "/>" where as I need it to insert
after the last "/>". Or I need to insert before the last "</"

If anyone could help with this is would be greatly appreciated.

Cheers

Ed Morton

2006-07-19, 7:56 am

ianbacon999@hotmail.com wrote:
> Hi, I need help inserting text into a file.

<snip>
> cat jms.bak | nawk -v filename=$JMS_INSERTFILE '
> BEGIN{if (filename=="")
> {
> print "Error:no filename given";
> exit 1;
> }
> }
> !/\<\/queue\>/ {print}
> /\/\>/ {while( getline<filename) print;}
> ' > jms.xml
>
> but this inserts after the first "/>" where as I need it to insert
> after the last "/>". Or I need to insert before the last "</"
>
> If anyone could help with this is would be greatly appreciated.


You need to read the file twice. First to determine which is the last
occurrence of the pattern and second to insert the text, e.g.

awk -v filename="$JMS_INSERTFILE" '
NR==FNR && /\/\>/ { lineNr=NR; next }
!/\<\/queue\>/ {print}
FNR==lineNR { while( getline<filename) print;}
' jms.bak jms.bak

Be careful when using getline as it has many caveats. For example, the
above will change the value of $0 so if you wanted to insert the
contents of "filename" BEFORE the line with the matching pattern in the
original file, then you'd have a problem because the $0 after the
getline loop would be the last record from "filename", not the current
record from "jms.bak".

If you don't want to manually specify the input file name twice on the
command line, add this to the BEGIN section instead:

ARGV[ARGC++]=ARGV[1]

Regards,

Ed.
Xicheng Jia

2006-07-19, 7:56 am

ianbacon999@hotmail.com wrote:
> Hi, I need help inserting text into a file.
>
> Here's what I have so far
>
> #!/bin/bash
> if [ $# -ne 1 ]; then
> echo "Usage:$0 insert "
> exit
> fi
>
> JMS_INSERTFILE=$1
>
> cat jms.bak | nawk -v filename=$JMS_INSERTFILE '
> BEGIN{if (filename=="")
> {
> print "Error:no filename given";
> exit 1;
> }
> }
> !/\<\/queue\>/ {print}
> /\/\>/ {while( getline<filename) print;}
> ' > jms.xml
>
> but this inserts after the first "/>" where as I need it to insert
> after the last "/>". Or I need to insert before the last "</"
>
> If anyone could help with this is would be greatly appreciated.
>
> Cheers


Maybe you can try:

awk -F'\>' -v OFS='\>' -v ins="`cat $JMS_INSERTFILE`" '
NF > 1 { $NF = ins $NF }1' jms.xml

Xicheng

Ed Morton

2006-07-19, 6:57 pm

Ed Morton wrote:
<snip>

Ooops.

> awk -v filename="$JMS_INSERTFILE" '
> NR==FNR && /\/\>/ { lineNr=NR; next }


Change the above to:

NR==FNR { if ($0 ~ /\/\>/) lineNr=NR; next }

to make sure you always do a "next" for every line of the file on the
first pass, not just the line that matches the pattern.

> !/\<\/queue\>/ {print}
> FNR==lineNR { while( getline<filename) print;}
> ' jms.bak jms.bak


Regards,

Ed.
ianbacon999@hotmail.com

2006-07-19, 6:57 pm

Thanks for this it works great. One further question - how do i insert
before the last </?


Ed Morton wrote:
> Ed Morton wrote:
> <snip>
>
> Ooops.
>
>
> Change the above to:
>
> NR==FNR { if ($0 ~ /\/\>/) lineNr=NR; next }
>
> to make sure you always do a "next" for every line of the file on the
> first pass, not just the line that matches the pattern.
>
>
> Regards,
>
> Ed.


ianbacon999@hotmail.com

2006-07-19, 6:57 pm

When all was going sooo well. I've embedded this into a script and
when run within this script the file get corrupt. It works on its own
though

Ed Morton wrote:
> Ed Morton wrote:
> <snip>
>
> Ooops.
>
>
> Change the above to:
>
> NR==FNR { if ($0 ~ /\/\>/) lineNr=NR; next }
>
> to make sure you always do a "next" for every line of the file on the
> first pass, not just the line that matches the pattern.
>
>
> Regards,
>
> Ed.


Harlan Grove

2006-07-19, 6:57 pm

Ed Morton wrote...
....
>Ooops.

....
>Change the above to:
>
>NR==FNR { if ($0 ~ /\/\>/) lineNr=NR; next }

....[color=darkred]
....

There's another bug, lineNR rather than lineNr. Case sensitivity can be
a PITA.

Wouldn't using tac | awk '..insert before first instance..' | tac be
cleaner?

dfeustel@mindspring.com

2006-07-19, 6:57 pm

Why not use ex to read in the entire file.
Then search backwards from the EOF til you find the
first '>'.
Then insert the text after that character?
That could all be done as a very simple batch script.
Xicheng Jia

2006-07-19, 6:57 pm

dfeustel@mindspring.com wrote:
> Why not use ex to read in the entire file.
> Then search backwards from the EOF til you find the
> first '>'.
> Then insert the text after that character?
> That could all be done as a very simple batch script.


The OP can also use any tools which support Perl-compatible regex's
lookahead construct(?!...), like:

v=`cat insert_file` perl -0777pe 's~/>(?!.*/> )~/>$ENV{v}~s' file.xml
v=`cat insert_file` ruby -0777pe 'sub(%r{/>(?!.*/> )}m,"/>"+ENV["v"])'
file.xml

which insert the whole contents of a file right after the last instance
of '/>' in file.xml

Xicheng

Ed Morton

2006-07-19, 9:56 pm

ianbacon999@hotmail.com wrote:
> Thanks for this it works great. One further question - how do i insert
> before the last </?


Just change the pattern from /\/\>/ to /<\//. And please don't top-post.

Ed.

>
> Ed Morton wrote:
>
>
>

Ed Morton

2006-07-19, 9:56 pm

ianbacon999@hotmail.com wrote:

> When all was going sooo well. I've embedded this into a script and
> when run within this script the file get corrupt. It works on its own
> though
>


Then there's something wrong with your script that calls it. Maybe
you're trying to write back to the same file you're reading from while
you're reading it?

Ed.

> Ed Morton wrote:
>
>
>

Ed Morton

2006-07-19, 9:56 pm

Harlan Grove wrote:

> Ed Morton wrote...
> ...
>
>
> ...
>
>
> ...
>
>
> ...
>
> There's another bug, lineNR rather than lineNr.


Thanks.

Case sensitivity can be
> a PITA.
>
> Wouldn't using tac | awk '..insert before first instance..' | tac be
> cleaner?
>


tac isn't always available and if you're going to use awk anyway....

Ed.
ianbacon999@hotmail.com

2006-07-20, 7:56 am


Ed Morton wrote:
> Harlan Grove wrote:
>
>
> Thanks.
>
> Case sensitivity can be
>
> tac isn't always available and if you're going to use awk anyway....
>
> Ed.


Thanks for all you help with this, I am now getting the results I want.
Cheers

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com