6

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)

3
  • can you edit input file by marking a '$' as end of line ?
    – Archemar
    Commented Nov 7, 2016 at 8:22
  • I can manipulate input.txt as long as it helps to get output.txt Commented Nov 7, 2016 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
    Commented Nov 7, 2016 at 8:51

3 Answers 3

12

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}'
2
  • Well, I didn't get it. where from you get these values? FIELDWIDTHS = "16 10 6 7" Commented Nov 7, 2016 at 8:31
  • I suggest to count them by hand (or by head -1 x | grep -Po '.*? (?=\S|$)' | awk '{print length}' )
    – JJoao
    Commented Nov 7, 2016 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
  • 1
    cool! (+1) I also liked numeration rule : it helps the reader.
    – JJoao
    Commented Nov 7, 2016 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}'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .