To replace the value of the column in a fixed width file

I have a fixed with file with header & trailer length having the same length of the detail record file.

The details record length of this file is 24, for Header and Trailer the records will be padded with spaces to match the record length of the file
Currently I am adding 3 spaces in header and 6 spaces in trailer to match with detail record length

current value of my header is
Column Name Data length
---------- ----------

A        1
B        2
C        2
D        8
E        8

current value of my trailer is

Column Name Data length
---------- ----------

A        1
B        2
C        15

My requirement is to change the value of the second column(Column B) from xx to yyy both in header and trailer.
After this change I should have only two spaces in header and 5 spaces in trailer

Can some one help here please

---------- Post updated at 05:03 AM ---------- Previous update was at 02:43 AM ----------

I have a fixed with file with header & trailer length having the same length of the detail record file.

The details record length of this file is 24, for Header and Trailer the records will be padded with spaces to match the record length of the file
Currently I am adding 3 spaces in header and 6 spaces in trailer to match with detail record length

current value of my header is

Column Name  Data length
----------   ----------
A        1
B        2
C        2
D        8
E        8

current value of my trailer is

Column Name  Data length
----------   ----------
A        1
B        2
C        15

My requirement is to change the value of the second column(Column B) from xx to yyy both in header and trailer.
After this change I should have only two spaces in header and 5 spaces in trailer

I don't fully understand.
If you need a fixed record size, use printf:

awk '(NR<=2) {printf "%-24s\n",$0; next} ($1=="B") {printf "%-13s%-11s\n",$1,$2}' file

To change a certain value on the fly, you can use

{
awk '(NR<=2) {printf "%-24s\n",$0; next} ($1=="B") {$2="yyy"} {printf "%-13s%-11s\n",$1,$2}' header
cat detail
awk '(NR<=2) {printf "%-24s\n",$0; next} ($1=="B") {$2="yyy"} {printf "%-13s%-11s\n",$1,$2}' trailer
} > newfile

Thanks for the reply.
Let me explain the requirement again

I have a file with header and trailer which is fixed width
Header is having five columns & trailer is having 3 columns.The respective length of each column I have mentioned below.

Column Name  Data length
----------   ----------
A        1
B        2
C        2
D        8
E        8

current value of my trailer is 

Column Name  Data length
----------   ----------
A        1
B        2
C        15

sample records for header :-

1cc  12345   43434            

I need to replace the above sample record second column value with yyy.i.e from cc to yyy.

1yyy  12345  43434            

So you need to split the data into 3 (x , xx and xxxxxxxxxxxxxxx) overwriting the second potion with "yyy" ?

perl -ne 'print substr($_ ,0,1),"yyy",subsr($_,3)' file_name

---------- Post updated at 02:53 PM ---------- Previous update was at 02:53 PM ----------

So you need to split the data into 3 (x , xx and xxxxxxxxxxxxxxx) overwriting the second potion with "yy" ?

perl -ne 'print substr($_ ,0,1),"yy",subsr($_,3)' file_name

Thank you..

I tried but its not working..Mine is a unix machine, In which pearl command is not working

This replaces position 2-3 with yyy, shifting the remainder by +1

sed 's/\(.\{1\}\)../\1yyy/'
1 Like

Thanks a lot.Its working fine.

if possible can you please tell me how to replace only the header & trailer of the file rest of the records need to be the same

---------- Post updated 08-03-13 at 12:48 AM ---------- Previous update was 08-02-13 at 07:17 PM ----------

sed 's/\(.\{1\}\)../\1yyy/'

This command is actually replacing the value of all the records in the file.But I need to replace the value of header & trailer only .Please some one help here

What's the difference between the 3 sections header,detail,trailer?
Could you give 3 example lines for each? (To find a contents criterion.)
Perhaps there are fixed line numbers, e.g. trailer starts at line 100 or is 10 lines long?

Please find the below record.In this the first and the last record is header & trailer.

HAR  1129201202:33:13   
D3065507                           
TAR000000000000144      

Suppose the file name is Test123.txt if I use the command

sed 's/\(.\{1\}\)../\1yyy/' Test123.txt it will give me the result as mentioned below

Hyyy  1129201202:33:13   
Dyyy65507                          
Tyyy000000000000144 

It should not be like above .It should change only for header & trailer and also it is adding one extra space at the end.I don't want that space

I have copied the CODE segments from your last post replacing each space character with a lowercase letter s as shown here:

HARss1129201202:33:13sss
D3065507sssssssssssssssssssssssssss
TAR000000000000144ssssss

and

Hyyyss1129201202:33:13sss
Dyyy65507ssssssssssssssssssssssssss
Tyyy000000000000144s

So, you will note that the output doesn't have an additional space character in the last line of your output; instead, it is missing five space characters. This change in the number of spaces at the end of the last line in your output was not caused by the sed command:

sed 's/\(.\{1\}\)../\1yyy/' Test123.txt

You must be doing something else that you haven't shown us that is making that change.

Its actually my mistake when I did a copy ..

I don't know how I can make my requirement understand :wink:

HAR  1129201202:33:13   
D3065507                
TAR000000000000144      

In the above example which I show you , I need to replace AR with YYY.
The below code will replace for all the three records, but I need to replace only for the first and last record .And also while replacing, it shouldn't add an extra space.It should remove one space and add that record Means Length should be only 24.
Note: -Its a fixed width file.All the records will have a length of 24
sed 's/\(.\{1\}\)../\1yyy/'

I created a file with your posted data. Two things to note here:
(1) I replaced all spaces by "*" so they are easily visible.
(2) The length of each line is 24. It wasn't so in your post, but I think that was due to copy/paste issues.

Here's my file:

$ 
$ cat f01
HAR**1129201202:33:13***
D3065507****************
TAR000000000000144******
$ 
$ # check length of each line
$ awk '{print length}' f01
24
24
24
$ 
$ 

Now you mention two things in your post -

(a) you want to replace all "AR"s by "yyy"
(b) you want to replace only first and last record (the head and tail record)

So, will "AR" be present only in the first and last record i.e. only in the head and tail record? Let's say it does. Then we can use "AR" to match the lines we want to change:

$ 
$ 
$ sed '/^.AR/{s/AR/yyy/; s/.$//}' f01
Hyyy**1129201202:33:13**
D3065507****************
Tyyy000000000000144*****
$ 
$ 

Here, "/^.AR/" means - "find out all lines that have any character at the beginning, followed by AR". This will work only on the first and last line. The second line will remain as it is.

The first operation "s/AR/yyy/" performs the required substitution.

The second operation "s/.$//" removes the last character in the line so that the length is constant. Note that it removes the last character - which could be a space or something else.

1 Like

Thanks for the reply
Actually I am getting below issue

sed: command garbled: /^.AR/{s/AR/yyy/; s/.$//}

Can you please look into this

A semi-colon is missing:

$ sed '/^.AR/{s/AR/yyy/; s/.$//;}' f01
2 Likes

Now to the addressing. You still haven't said a word about the number of lines per section.
This substitutes in lines 1...1 and in lines 3...3 only (as you have given for header and trailer in your last example)

sed '
1,1 {s/\(.\{1\}\)../\1yyy/; s/ $//;}
3,3 {s/\(.\{1\}\)../\1yyy/; s/ $//;}
' file

The same is to substitute in all lines but lines 2...2 (the detail section in your last example):

sed '
2,2 !{s/\(.\{1\}\)../\1yyy/; s/ $//;}
' file

And it deletes a space at the end.
Of course a contents-addressing can solve it, too

sed '
/^.AR/ {s/\(.\{1\}\)../\1yyy/; s/ $//;}
' file