5

I have a sample as shown here:

input.txt

   USERS        position   ref   rslt   
    usr1                    X     B   
    usr2          2980            C   
    usr3          3323      P      
    usr4                          A  
    usr5          5251      U      
    usr6          9990            A
    usr7          10345     T     

I need to print "rslt" column and corresponding "USERS", output file should be like this:

output.txt

  USERS     rslt   
   usr1       B   
   usr2       C       
   usr4       A
   usr6       A 

I tried to use awkcommand but it didn't work. Note that, all black position of the table is filled with spaces (No. of spaces is different in each row)

  • can you edit input file by marking a '$' as end of line ? – Archemar Nov 7 '16 at 8:22
  • I can manipulate input.txt as long as it helps to get output.txt – Mishkat Hasan Nov 7 '16 at 8:29
  • I just want to see in your sample field lenght, if it is fixed length, then we can see if last char is non space. – Archemar Nov 7 '16 at 8:51
11

In this case, one possible solution is to provide the widths of the fields in the beginning section:

awk 'BEGIN {FIELDWIDTHS = "16 11 6 7"} 
    $4 ~/[^ ]/ {print $1 $4}' 

Fieldwidths may be counted by hand, but for complex headers I like to start with

 head -1 f | grep -Po '.*? (?=\S|$)' | awk '{print length}'

UPDATE: ... or in order to deal with initial and final spaces in the header:

 head -1 f | grep -Po '(^ *|\S).*?( (?=\S)|$)' | awk '{print length}'
  • Well, I didn't get it. where from you get these values? FIELDWIDTHS = "16 10 6 7" – Mishkat Hasan Nov 7 '16 at 8:31
  • I suggest to count them by hand (or by head -1 x | grep -Po '.*? (?=\S|$)' | awk '{print length}' ) – JJoao Nov 7 '16 at 8:41
6

The awk command isn't the most appropriate tool for this job. Use cut, which takes as an argument the character positions of the fields you want to extract. So in your example specify that USERS starts from character position 1 and ends in character position 8 and rslt starts on character position 33.

$ cut -c 1-8,33- input.txt
   USERS rslt
    usr1  B
    usr2  C
    usr3
    usr4  A
    usr5
    usr6  A
    usr7

See the following on how to count character positions.

         1         2         3         
123456789012345678901234567890123456789
   USERS        position   ref   rslt   
    usr1                    X     B   
    usr2          2980            C   
    usr3          3323      P      
    usr4                          A  
    usr5          5251      U      
    usr6          9990            A
    usr7          10345     T      
  • 1
    cool! (+1) I also liked numeration rule : it helps the reader. – JJoao Nov 7 '16 at 14:09
1

You can get almost there by using the unexpand utility to 'tabify' the input, then setting the awk field separator to tab and only printing lines whose final field consist of something other than spaces:

unexpand -t8 input.txt | awk -F'\t' '$NF ~ /[^ ]/ {print $1, $NF}'
    usr1   B
    usr2   C
    usr4   A
    usr6   A

It doesn't work for the header line because there are fewer spaces between the position and ref fields. If the header is a must have, you could handle that separately:

unexpand -t8 input.txt | awk -F'\t' 'NR == 1 {print $1,$3} $NF ~ /[^ ]/ {print $1, $NF}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.