Operating System - HP-UX
1829265 Members
2111 Online
109988 Solutions
New Discussion

change 5th line after a pattern - AWK

 
SOLVED
Go to solution
user57
Occasional Advisor

change 5th line after a pattern - AWK

I have a requirement to assign a value "xxx" to mode in the below file.

I am able to print the mode line (awk's default action). How can I assign this 5th line to a variable so as to change its value and then print it i.e print:
mode = XXX

I am looking for an awk solution.

file:

/usr/sbin/bootpd:/
type =
class =
owner =
group =
mode =
checksum =
size =


$ awk '!--c;/\/usr\/sbin\/bootpd:/ { c=5 }' file

mode =
11 REPLIES 11
TTr
Honored Contributor

Re: change 5th line after a pattern - AWK

What are you setting the "mode=" to?

And why are you searching for the 5th line under the /usr/sbin/bootpd" pattern? Can't you search for the "mode" pattern and set it? Are there different types of "mode=" lines that are not related to the /usr/sbin/bootpd line?
Rick Garland
Honored Contributor

Re: change 5th line after a pattern - AWK

Here is something that may be of help. Uses sed and awk. The sed is used to print the 3rd line of a file, the awk is pattern matching. For you, make the necessary changes to to print 5th line. If the pattern matches, can use sed again to substitute your desired value in its place. Make the changes you need and as always, test.


#!/bin/sh

charset=us-ascii
export charset


find /apps/sci/loaded -type f -mtime 0 -print > /apps/sci/loaded/scifiles

for FILE in /apps/sci/loaded/scifiles
do
cat $FILE |\
while read line
do
SCI=`sed -n 3,3p $line | awk '/046/ && /TOWER/ {print $0}' $line`
if [ "$SCI" != "" ]
then
if [ "$line" = "/apps/sci/loaded/scifiles" ]
then
echo "$line" > /dev/null
elif [ "$line" = "/apps/sci/loaded/mailedtosci.list" ]
then
echo "$line" > /dev/null
elif [ "$line" = "/apps/sci/loaded/mailsci.sh" ]
then
echo "$line" > /dev/null
else
mailx -s "Decoder File `basename $line`" garlric@exchange1 < $line
echo "`basename $line` `date +'%b %d %Y %X'`" >> mailedtosci.list
fi
fi
done
done
Hein van den Heuvel
Honored Contributor

Re: change 5th line after a pattern - AWK

Do you always want to change the 5th line, or do you want to change the line starting with 'mode'


>> I am looking for an awk solution.
Hmm, why? Apparently you do not know awk too well, or at least not yet. Sorry. Couldn't resist!

Anyway.... assuming you want the line with 'mode=' and assuming you want the xxx to be a variable and assuming you want to stick it back into a file, you may want to try:

# awk -v mode=TEST '/^mode/{$0 = $0 mode} 1' x > y

This reads the file x,
writes to y,
sets up a variable called mode to value TEST.
The passes an awak 'one-liner'.
The one-liner first looks for a line starting with 'mode, and if it finds that ads the variable 'mode' to the end.
The next instruction is '1' which is true and causes awk to do the default thing... print $0.

hth,
Hein.
Hein van den Heuvel
Honored Contributor

Re: change 5th line after a pattern - AWK

Oops, hit submit before adding the example.
And please clarify what you mean with 'after a pattern'.
Could the same line be found earlier?
Could the same line be found later?

So maybe you want something along the lines of the one liner below.
If only starts looking for mode when a 'begin' has been set by looking for the bootpd line.
It stops looking when it has seen one.

$ cat x
/usr/sbin/too early/
mode =
/usr/sbin/bootpd:/
type =
class =
owner =
group =
mode =
checksum =
size =
/usr/sbin/too late/
mode =
checksum =

$ awk -v mode=TEST '/bootpd:/{beg++} beg && ! end && /^mode/ {$0 = $0 mode; end++} 1' x
/usr/sbin/too early/
mode =
/usr/sbin/bootpd:/
type =
class =
owner =
group =
mode =TEST
checksum =
size =
/usr/sbin/too late/
mode =
checksum =


Enjoy!
Hein.
James R. Ferguson
Acclaimed Contributor

Re: change 5th line after a pattern - AWK

Hi:

Rather interesting.

# awk '!--c {print $0,"XXX"};/\/usr\/sbin\/bootpd:/ { c=5 }' file
mode = XXX

Regards!

...JRF...


Dennis Handly
Acclaimed Contributor

Re: change 5th line after a pattern - AWK

If you want to change all of the "mode=" you can use ch_rc(1m):
/usr/sbin/ch_rc -a -p "mode=99" file
user57
Occasional Advisor

Re: change 5th line after a pattern - AWK

Thanks all. I appreciate this task is best solved using sed - and wasn't explained very well initially. The input file is composed of many 8 line stanza's with the format:

attribute = value

I was merely trying to change the value of one attribute (mode) in one stanza (bootpd) leaving all other values/stanza's unchanged.

I think there's enough in the combined response to achieve the task in awk.
James R. Ferguson
Acclaimed Contributor
Solution

Re: change 5th line after a pattern - AWK

Hi (again):

> I was merely trying to change the value of one attribute (mode) in one stanza (bootpd) leaving all other values/stanza's unchanged.

Then here's an alternative solution:

# perl -pe '?/usr/sbin/bootpd:?..?mode? and s{(mode =)}{$1 "xxx"}' file

If you want to update "in-place" simply do:

# perl -pi.old -e '?/usr/sbin/bootpd:?..?mode? and s{(mode =)}{$1 "xxx"}' file

...which leaves an unmodified copy of the original file as "file.old".

Regards!

...JRF...
Hein van den Heuvel
Honored Contributor

Re: change 5th line after a pattern - AWK

Ah, so contrary to the original question, but in line with what we all expected, the lines do have values on them already.

I forgot to consider the awk range selector as an option to to solve this. It looks a little cleaner than maintaining flags as I suggested.
For example:


$ awk -v mode=TEST '/bootpd:/,/^mode/ {if (/^mode/) $0="mode = " mode} 1' x
/usr/sbin/too early/
mode =
/usr/sbin/bootpd:/
type =
class =
owner =
group =
mode = TEST
checksum =
size =
/usr/sbin/too late/
mode =
checksum =

Hein.
user57
Occasional Advisor

Re: change 5th line after a pattern - AWK

Thank you JRF for the excellent response - spot on! I thought of a relatively straight-forward approach to the problem. Changing the desired value and preserving all others:

awk 'BEGIN { FS="\n"; RS=""; OFS="\n"; ORS="\n\n" }

$0 !~/^\/usr\/sbin\/bootpd:/ { print }

$1 ~/^\/usr\/sbin\/bootpd:/ {
$6=" mode = r-xr-xr-x"
print
} ' file


Thank you also Hein for the most recent post. I haven't actually tested it as I was working on an alternative solution and reviewing JRF's perl approach.
user57
Occasional Advisor

Re: change 5th line after a pattern - AWK

Just reviewed your post Hein - a neat solution.

Thanks