2

I'm trying to simply print column $4 followed by $NF with the following data:

       000   0     00    NUL '\0' (null character)   100   64    40    @
       001   1     01    SOH (start of heading)      101   65    41    A
       002   2     02    STX (start of text)         102   66    42    B
       003   3     03    ETX (end of text)           103   67    43    C
       004   4     04    EOT (end of transmission)   104   68    44    D
       005   5     05    ENQ (enquiry)               105   69    45    E
       006   6     06    ACK (acknowledge)           106   70    46    F
       007   7     07    BEL '\a' (bell)             107   71    47    G
       010   8     08    BS  '\b' (backspace)        110   72    48    H

so that I get:

NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
@
A
B
C
D
E
F
G
H

Where awk waits for the first operation to finish then performs a printout of the next column.

I tried:

awk '{print $4} {print $NF}' 

but this obviously just prints them one after the other and mixes them all up.

I'm trying to better understand awk and messing around, bear with me.

3 Answers 3

6

AFAIK you would need to store the $NF values and print them in an END block

awk '{a[NR] = $NF; print $4} END{for(i=1;i<=NR;i++) print a[i]}' file

or make two passes over the file

awk 'NR==FNR {print $4; next} {print $NF}' file file
1
  • thank you this is exactly what i was looking for
    – Mathew
    Commented Oct 15, 2023 at 13:52
3

@steeldriver already showed how to do this entirely in awk and while this is more than you need for this specific problem, consider also the extremely useful Decorate-Sort-Undecorate idiom for problems like this:

$ awk -v OFS='\t' '{print 1, NR, $4 ORS 2, NR, $NF}' file | sort -nk1,2 | cut -f3-
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
@
A
B
C
D
E
F
G
H

You could implement something similar entirely in GNU awk (for arrays of arrays and sorted_in) as:

$ awk '
    { a[1][NR]=$4; a[2][NR]=$NF }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"
        for (i in a) for (j in a[i]) print a[i][j]
    }
' file
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
@
A
B
C
D
E
F
G
H
3

Using awk:

$ awk '{print $4; a = ((a) ? a ORS : "") $NF} END{print a}' file

A simpler and more efficient way as suggested by @EdMorton is

$ awk '{print $4; a=a $NF ORS} END{printf "%s", a}' file

Using awk and datamash:

$ awk '{print $4, $NF}' file | datamash -W --output-delimiter $'\n' transpose

The following command gives the output as:

$ awk '{print $4, $NF}' ex | datamash -W  transpose 
NUL     SOH     STX     ETX     EOT ENQ      ACK     BEL     BS
@       A       B       C       D     E        F     G       H

In this output values are separated by tab that can be changed by setting --output-delimiter to \n.

$ awk '{print $4, $NF}' ex | datamash -W --output-delimiter $'\n' transpose
NUL
SOH
STX
ETX
EOT
ENQ
ACK
BEL
BS
@
A
B
C
D
E
F
G
H
0

You must log in to answer this question.

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