How to replace a line content

Hi Experts,

I have binary files contain an ID Line as:

:
:
$Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10 pkm ship$
:
:

where the ID Line format is:
$Header: <File_Name> <Version> <Last_update_date_time> pkm ship$

In this Example:
File_Name = FNDSCMON.fmb
Version = 115.6
Last_update_date_time = 2000/01/11 10:26:10

I want to write a script to update the ID Line as:
File_Name = the file name
Version = old_version + 0.1
Last_update_date_time = current date_time

so, the new ID line should be show as:
:
:
$Header: <the file name> <old_version + 0.1> <current date_time> pkm ship$
:
:

Can anyone help?

Thanks!

Victor Cheung

This should do the job:

#!/bin/sh

curr_dat=`date "+%Y\/%d\/%m"`
curr_time=`date "+%H:%M:%S"`

awk -v ver="old_version + 0.1" -v dat=$curr_dat -v t=$curr_time '
/^\$Header:/{$2=FILENAME;$3=ver;$4=dat;$5=t}1
' file

Regards

Hi Frank,

Sorry, I think I have uncompleted mentions of my question, here is the complete one, can you please help? :

I have binary files contain an ID Line as:

:
:
$Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10 pkm ship$
:
:

where the ID Line format is:
$Header: <File_Name> <Version> <Last_update_date_time> pkm ship$

In this Example:
File_Name = FNDSCMON.fmb
Version = 115.6
Last_update_date_time = 2000/01/11 10:26:10

I want to write a script to update the ID Line as:
File_Name = the file name
Version = version + 0.1
Last_update_date_time = current date_time

so, the new ID line should be show as:
:
:
$Header: <the file name> <version + 0.1> <current date_time> pkm ship$
:
:

  • The line starts with "$Header:" and ends with "pkm ship$"
  • The new line length have to be kept as same as the old line length (the whitespaces is adjustable)
  • perl should be used for the replacment action (The files I want to change are binary files, using other command, such as, sed will make the file unusable)

Can you help how to write the script?

Many Thanks!
Victor Cheung

In that case you have to provide more information, what is the exact length of the fields, beginning in what position?

Regards

Hi Frank,

The exact length between the Start Pattern,$Header:, and the End Pattern,pkm ship$, is fixed to 80 characters,

e.g.1:
$Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10........................pkm ship$

could be changed as :

$Header: FNDSCMON.fmb 115.7 2008/04/21 13:29:09........................pkm ship$

or, e.g.2:
Other Word $Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10........................pkm ship$

could be changed as :

Other Word $Header: FNDSCMON.fmb 115.7 2008/04/21 15:36:50........................pkm ship$

p.s. please replace the .... as whitespaces, multi whitespaces will be trunced when posted to this forum, so I use .... instead.

Many Thanks!
Victor Cheung

Try this:

#!/bin/sh

curr_dat=`date "+%Y\/%m\/%d"`
curr_time=`date "+%H:%M:%S"`

awk -v dat=$curr_dat -v t=$curr_time -v name="old_version" -v ver="0.1" '
/^\$Header:/{
$2=sprintf("%-12s",name)
$3=sprintf("%-5s",ver)
$4=sprintf("%-10s",dat)
$5=sprintf("%-31s",t)
}1
' file

Regards

perl -pe 's!(\$Header: \S+ )(\d+\.\d+) (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})( +pkm ship\$)\n!
    my ($head, $ver, $date, $tail) = ($1, $2, $3, $4);
    my @now = gmtime();
    sprintf "%s %3.1f %04i/%02i/%02i %02i:%02i:%02i%s\n",
      $head, $ver+0.1, $now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1], $now[0], $tail !e' file

... assuming you want the date stamp in GMT (you probably do, even if you think you don't).

The version will monotonously grow by 0.1 for each update; so after 115.9 you get 116.0, 116.1, etc. Hope you won't need to go beyond 999.9 because this code won't handle that (without wrecking the fixed-length constraint).

I don't have anything really to test this on, but report back if it doesn't work.

time=`date '+%m/%d/%y %H:%M:%S`
nawk -v t="$time" '{
if ($1 ~ /\$Header:/ )
printf("%s %s %f %s pkm ship$\n",$1,$2,$3+0.1,t)
else
print
}' filename

summer_cherry,

The OP also wants replace the filename and version and also to keeps the exact length of a record.

Regards.

Also note that the $Header keyword is not necessarily at start of line, or the first field.

I was under the impression that the file name should stay.

Hi Era,

Assume that I have a file VT100.fmm with content:

$Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10........................pkm ship$
Other Word $Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10........................pkm ship$
$Header: FNDSCMON.fmb 115.6 2000/01/11 10:26:10........................pkm ship$

and I convert it with:

perl -pe 's!(\$Header: \S+ )(\d+\.\d+) (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})( +pkm ship\$)\n!
my ($head, $ver, $date, $tail) = ($1, $2, $3, $4);
my @now = gmtime();
sprintf "%s %3.1f %04i/%02i/%02i %02i:%02i:%02i%s\n",
$head, $ver+0.1, $now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1], $now[0], $tail !e' VT100.fmm

and I view the file using vi, but the lines were not changed, can you please help?

Thanks!
Victor Cheung

If the $Header keyword is not at the start of line:

 #!/bin/sh

curr_dat=`date "+%Y\/%m\/%d"`
curr_time=`date "+%H:%M:%S"`

awk -v dat=$curr_dat -v t=$curr_time -v name="old_version" -v ver="0.1" '
/\$Header:/{
$2=sprintf("%-12s",name)
$3=sprintf("%-5s",ver)
$4=sprintf("%-10s",dat)
$5=sprintf("%-31s",t)
}1
' file

Regards

If it's not even $1, the field numbers are wrong, too. Up in comment #5 victorcheung writes:

Anyway, awk is not necessarily very robust when it comes to handling binary files, whereas Perl supposedly is.

Hi Era,

Thank you very much, it works!!

Hi Frank and Summer,

Thank you for your help!! But the perl works for binary file.

Thanks again!!
Victor Cheung