sed to have defined positionning on line

Hi,
I'd like to know how to use sed to position my output to a defined location on a line.

Here is my example:
A: filename.txt => line x : comment fromA
B: very longfilename.txt => line xyzabd : commentfromB

and I'd like to have as output from sed :

A: filename.txt................=> line x................: comment fromA
B: very longfilename.txt....=> line xyzabd........: commentfromB

In fact, i need to know how to rearrange and get aligned columns whatever my A and B internal fields are ?

Thanks a lot.....

:wink: :wink: :wink:

I would suggest awk as a reformatter. There are many different approaches to identifying and isolating the various pieces of a line. In the following, awk uses the "=>" and the colon that occurs beyond that to identify segments of the line, then prints the line with an exact format.

Those widths on the print command are minimum column widths. If a line segment comes in that exceeds those minimums, the longer segments will be accommodated, thus pushing the columns out of alignment for that one line. We could easily truncate instead, but we don't want that. I kept the overall width to fit in 80 columns, but an output line can be up to about 2400 characters.

I did not do the dot-fill at this time. I did not check for bad data. If a line is missing the "=>" for example, the entire line would be seen as segment 1.

#!/bin/sh
awk '{
FS="=>"
part1=$1
$0=$2
FS=":"
printf "%-28s=>%-14s:%-34s\n",part1,$1,$2
}' myfile > myNEWfile
exit 0

Thanks Jimbo,
I'm going to try asap.
Have a nice day :slight_smile: :smiley: :slight_smile:

I still receive an error message :

awk: can't set $0
record number 1

here is a right copy of my original line :
src**>...hwi_adc.....=>...Line...332:..../*..comments...../
cin**>...hwi_resource_manager.....=>...Line...33333:..../*..comments.....
/

(of course don't take care of ......)

And my goal is to get:
src**>...hwi_adc........................=>...Line...332......./*..comments...../
cin**>...hwi_resource_manager.....=>...Line...33333..../*..comments.....
/

Any idea ? :confused:

Hmmm ...
I'm going to guess, for now, that your awk does not like making changes to the current buffer line, either entire line ($0) or even individual fields on the line like $1. Bummer, because I use that a lot on HP-UX. What is your platform?

OK, following is a solution that does not modify the buffer. It first identifies where in the line the => and the first /* are. It then generates pad1 and pad2 to be the required # dots to force the => to col 35 and the /* to col 57 (35+22). If an input line is already beyond these, nothing will get truncated, pad1 and pad2 will just be null for these.

Some platforms do not handle the quoted awk program spanning multiple lines, but I don't think you have that issue. If so, we can put line continuations and semicolons, or just bring in the awk code with the -f option.

#!/bin/sh
awk '{
aloc=index($0,"=>")
cloc=index($0,"/*")
pad1=substr("....................",1,35-aloc)
pad1len=length(pad1)
pad2=substr("....................",1,57-cloc-pad1len)
print substr($0,1,aloc-1) pad1 \
      substr($0,aloc,cloc-aloc) pad2 \
      substr($0,cloc)
}' myfile > myNEWfile
exit 0

Hi Jimbo,
sorry for the delay but I'm just back from vacation....some fresh air will help to think....
My platform is Sun Solaris OS 5.5.1 on Ultra 5.

Your solution does not work fine. Columns are not aligned yet.
Here is a cut and paste of my screen:

cin**> sk_5457.h => Line 1270 /--- approach, each i/o mapped on the TPU must use the specific TPU ---/
cin**> filter.c => Line 36 /* Lag_Filter_Approx_W -h- /
cin
*> filter.c => Line 272 CARDINAL Lag_Filter_Approx_W (register CARDINAL NewValue,
cin**> filter.c => Line 297 } /*** End of Lag_Filter_Approx_W /
cin
> filter.h => Line 35 /
Lag_Filter_Approx_W /
cin
*> filter.h => Line 87 CARDINAL Lag_Filter_Approx_W (register CARDINAL NewValue,
cin**> filter.h => Line 104 /* - Create Lag_Filter_Approx_W function to round up to the next /
cin
*> h_qadc64.c => Line 47 /--- This logic is called from the appropriate 58X event ---/
cin**> v_wdg.c => Line 623 /*** appropriate EEPROM or ETC received buffer. ***/

and here is what I would expect as a result :

cin **> sk_5457.h ...........=> Line 1270 .................:........../--- approach, each i/o mapped on the TPU must use the specific TPU ---/
cin *> filter.c ...................=> Line 36 .....................:........../ Lag_Filter_Approx_W -h- */
cin *> filter.c ...................=> Line 272 ...................:..........CARDINAL Lag_Filter_Approx_W (register CARDINAL NewValue,
cin > filter.c ...................=> Line 297 ...................:..........} /
End of Lag_Filter_Approx_W ***/
cin > filter.h ...................=> Line 35 .....................:........../ Lag_Filter_Approx_W /
cin **> filter.h ...................=> Line 87 .....................:..........CARDINAL Lag_Filter_Approx_W (register CARDINAL NewValue,
cin *> filter.h ...................=> Line 104 ...................:........../ - Create Lag_Filter_Approx_W function to round up to the next /
cin **> h_qadc64.c ........=> Line 47 ......................:........../
--- This logic is called from the appropriate 58X event ---
/
cin > v_wdg.c ...............=> Line 623 ...................:.........../
appropriate EEPROM or ETC received buffer. ***/

Do you see a solution ?
I was using the following awk but I get a problem when a "=" is part of left side....and I get only one sort on first "=>".

awk '{
FS="="
printf "%-35s=%s\n",$1,$2
}' /tmp/filea$$

In fact, the three missing columns to generate are :
at "=>" , at ":" and at start of last line (after the line number) which can be a comment or c code.

How do you concatenate a line with awk ? I was using something like :

{ for (i=6;i<=NF;i++)
part=part + $i" " }

but with no good result !

Thanks again,
homefp

homefp, I just ran my awk solution against the data you just posted, and it worked perfectly for me. What result do you get?

I am at a 3-day intense seminar, so I will have no significant time nor brain power to spare for next 2-3 days.

Hi Jimbo,
with your script , I get something like:

Sorry,
I did something wrong.....:confused:

here is what I get:
cin **> comm2.uc ...................................cin *> comm2.uc => Line 208 : ( the user should call Get_Time_LoW, which will load the appropriate *)
cin **> eqom_7.uc ..................................cin *> eqom_7.uc => Line 389 : ( UNUSED ENTRIES - execute appropriate termination *)
cin **> eqom_d.uc ..................................cin *> eqom_d.uc => Line 390 : ( UNUSED ENTRIES - execute appropriate termination *)
cin **> eqom_e.uc ..................................cin *> eqom_e.uc => Line 389 : ( UNUSED ENTRIES - execute appropriate termination *)
cin **> globals.uc .................................cin *> globals.uc => Line 406 : ( - Made changes appropriate to cam edge filtering modifications. *)
cin > hwi_rm_mios1.c ...........=> Line 138 : ......../ determine which flag generated the int and call the appropriate/
cin *> hwi_rm_mios1.c ...........=> Line 145 : ..../ - uncomment the appropriate slot */
cin *> hwi_rm_mios1.c ...........=> Line 146 : ..../ - add a call to the appropriate handler */
cin > hwi_rm_mios1.c ...........=> Line 258 : ......../ determine which flag generated the int and call the appropriate/
cin *> hwi_rm_mios1.c ...........=> Line 265 : ..../ - uncomment the appropriate slot */
cin *> hwi_rm_mios1.c ...........=> Line 266 : ..../ - add a call to the appropriate handler /
cin **> hwi_spi.c ................=> Line 123 : ....../
-- Enable spi devices by setting appropriate discrete output */
cin **> nitc1.uc ...................................cin *> nitc1.uc => Line 301 : ( UNUSED ENTRIES - execute appropriate termination. *)
cin **> rqom.uc ....................................cin *> rqom.uc => Line 438 : ( UNUSED ENTRIES - execute appropriate termination *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 453 : $ 1 406 ( - Made changes appropriate to cam edge filtering modifications. *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 908 : $ 1 390 ( UNUSED ENTRIES - execute appropriate termination *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 1338 : $ 1 301 ( UNUSED ENTRIES - execute appropriate termination. *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 3020 : $ 1 389 ( UNUSED ENTRIES - execute appropriate termination *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 3480 : $ 1 389 ( UNUSED ENTRIES - execute appropriate termination *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 5712 : $ 1 438 ( UNUSED ENTRIES - execute appropriate termination *)
cin **> scorpio.lst ................................cin *> scorpio.lst => Line 5999 : $ 1 208 ( the user should call Get_Time_LoW, which will load the appropriate *)
cin *> hwi_can.c ................=> Line 327 : ../ Select the appropriate CAN object set */
cin *> hwi_can.c ................=> Line 470 : ../ Select the appropriate CAN object set */
cin *> hwi_can.c ................=> Line 596 : ../ Select the appropriate CAN object set */
cin *> hwi_can.c ................=> Line 795 : ....../ Select the appropriate CAN device */
cin *> hwi_sci.c ................=> Line 540 : ......../ interrupt(s) and then calls the appropriate handling function(s). */
cin *> hwi_sci.c ................=> Line 736 : ......../ bytes as appropriate. */

Any idea ?
homefp

When you first posted some of your actual data ("here is a right copy of my original line", that limited sample showed that the comments were delineated with a traditional syntax for embedded comments: /*..comments...../. Now that you have posted more of your data, I can see that I cannot rely on the / to start your comments.

Without that, it is quite a bit more inconvenient. Start of comments must now be identified as the second word following the word "Line". This involves a little scanning of the line and some checking to ensure that I do not go into an infinite loop. The following code should do it. The only requirements for a data line are:

must contain =>
must contain Line to the right of =>
must have at least two words following Line
must have space-delimited words (not tab-delimited)

There is one rare situation that could cause this to loop, and that is if a data line violated BOTH of the last two rules. I could protect against that with gsub("\t"," ") but your awk does not want to modify $0.

I have the LINE REQUIREMENTS NOT MET just for testing. After testing, you will want to remove that, but you must leave the simple "print" just below it, which is the command that will print the unchanged line.

#!/bin/sh
awk '{
aloc=index($0,"=>")
cloc=index($0,"Line")+4
for (w=1;w<=NF;w++)
   if ($w=="Line") break
if (aloc==0 || cloc==4 || cloc<aloc || (w+2)>NF)
  {print "LINE REQUIREMENTS NOT MET - FOLLOWING LINE IS UNCHANGED:"
   print}
else
  {while (substr($0,cloc,1)==" ") cloc++
   while (substr($0,cloc,1)!=" ") cloc++
   pad1=substr("....................",1,35-aloc)
   pad1len=length(pad1)
   pad2=substr("....................",1,57-cloc-pad1len)
   print substr($0,1,aloc-1) pad1 \
         substr($0,aloc,cloc-aloc) pad2 \
         substr($0,cloc)}
}' myfile > myNEWfile
exit 0

Thanks Jimbo for your help.
It seems to work perfectly !
Have a nice day.:stuck_out_tongue: