showkey
showkey

Reputation: 358

How to combine the two awk files into one?

Here is a original awk file ,i want to format it.

input content----original awk file named test.txt

awk 'BEGIN {maxlength = 0}\
     {\
           if (length($0) > maxlength) {\
                maxlength = length($0);\
                longest = $0;\
           }\
     }\
     END   {print longest}' somefile

expected output----well-formatted awk file

awk 'BEGIN {maxlength = 0}                      \
     {                                          \
           if (length($0) > maxlength) {        \
                maxlength = length($0);         \
                longest = $0;                   \
           }                                    \
     }                                          \
     END   {print longest}' somefile

step1:to get the longest line and chracters number

step1.awk

#! /usr/bin/awk 
BEGIN {max =0 }
{
    if (length($0) > max) { max = length($0)}
}
END {print max}

awk -f step1.awk test.txt

Now the max length for all lines is 50.

step2 to put \ in the position 50+2=52.

step2.awk

#! /usr/bin/awk
{
if($0 ~ /\\$/){
    gsub(/\\$/,"",$0);
    printf("%-*s\\\n",n,$0);
    }
else{
    printf("%s\n",$0);
    }
}

awk -f step2.awk -v n=52 test.txt > well_formatted.txt

How to combine step1 and step2 into only one step,and combine step1.awk and step2.awk as one awk file?

Upvotes: 0

Views: 148

Answers (4)

James Brown
James Brown

Reputation: 37404

Here is one for GNU awk. Two runs, first one finds the max length and the second one outputs. FS is set to "" so that each char goes on its field and the last char will in $NF:

$ awk 'BEGIN{FS=OFS=""}NR==FNR{m=(m<NF?NF:m);next}$NF=="\\"{$NF=sprintf("% "m-NF+2"s",$NF)}1' file file

Output:

awk 'BEGIN {maxlength = 0}               \
     {                                   \
           if (length($0) > maxlength) { \
                maxlength = length($0);  \
                longest = $0;            \
           }                             \
     }                                   \
     END   {print longest}' somefile

Explained:

BEGIN     { FS=OFS="" }                         # each char on different field
NR==FNR   { m=(m<NF?NF:m); next }               # find m ax length
$NF=="\\" { $NF=sprintf("% " m-NF+2 "s",$NF) }  # NF gets space padded
1                                               # output

If you want the \s further away from the code, change that 2 in sprintf to suit your liking.

Upvotes: 1

Akshay Hegde
Akshay Hegde

Reputation: 16997

Better version, where you can use sub() instead of gsub(), and to avoid testing the same regexp twice sub(/\\$/,""){ ... }

awk 'FNR==NR{ 
             if(length>max)max = length 
             next
     }
     sub(/\\$/,""){
             printf "%-*s\\\n", max+2, $0
             next
     }1' test.txt test.txt

Explanation

awk 'FNR==NR{                             # Here we read file and will find, 
                                          # max length of line in file
                                          # FNR==NR is true when awk reads first file

             if(length>max)max = length   # find max length 
             next                         # stop processing go to next line
     }
     sub(/\\$/,""){                       # Here we read same file once again, 
                                          # if substitution was made for the regex in record then

             printf "%-*s\\\n", max+2, $0 # printf with format string max+2
             next                         # go to next line
     }1                                   # 1 at the end does default operation print $0, 
                                          # nothing but your else statement printf("%s\n",$0) in step2 
     ' test.txt test.txt

You have not shown us, what's your input and expected output, with some assumption,

if your input looks like below

akshay@db-3325:/tmp$ cat f
123      \
\
12345     
123456   \
1234567  \
123456789 
12345    

You get output as follows

akshay@db-3325:/tmp$ awk 'FNR==NR{ if(length>max)max = length; next}
sub(/\\$/,"",$0){ printf "%-*s\\\n",max+2,$0; next }1' f f
123         \
            \
12345     
123456      \
1234567     \
123456789 
12345  

Upvotes: 4

NeronLeVelu
NeronLeVelu

Reputation: 10039

awk '
   # first round 
   FNR == NR {
      # take longest (compare and take longest line by line)
      M = M < (l = length( $0) ) ? l : M
      # go to next line
      next
      }

   # for every line of second round (due to previous next) that finish by /
   /[/]$/ {          
      # if a modification is needed
      if ( ( l = length( $0) ) < M ) {
         # add the missing space (using sprintf "%9s" for 9 spaces)
         sub( /[/]$/, sprintf( "%" (M - l) "s/", ""))
         }
      }
  # print all line [modified or not] (7 is private joke but important is <> 0 )
  7
  ' test.txt test.txt

Note:

  • twice the file at the end is mandatory for reading twice the file
  • assume that there is nothing after last / (no space). Could be easily adapted but not the purpose
  • assume that line without / are not modified but still printed

Upvotes: 1

lpg
lpg

Reputation: 4937

Maybe something like this?

wc -L test.txt | cut -f1 -d' ' | xargs -I{} sed -i -e :a -e 's/^.\{1,'{}'\}$/& /;ta' test.txt && sed -i -r 's/(\\)([ ]*)$/\2\1/g' test.txt

Upvotes: 0

Related Questions