The following code should work:
awk -F'|' '{for (i=1;i<=NF;i++) {len=length($i); if (len>lval[i]) {lval[i]=len; lpos[i]=FNR;}}} END{for (i in lval) printf("Longest value of column %d: %d (line %d)\n",i,lval[i],lpos[i])}' contact_d.csv
For the above example, it returns
Longest value of column 1: 7 (line 1)
Longest value of column 2: 9 (line 1)
Longest value of column 3: 14 (line 1)
Longest value of column 4: 26 (line 2)
This script will, for every line, loop over all fields (from 1 to NF
, the number of fields) and see if the length of the field (temporarily stored in a variable l
) is greater than the longest length found so far, which is stored in an array variable lval
under the index of the field (=column) number.
On the first line, lval
is not yet initialized, and it will behave as if all lval[i]
were 0 (in reality, it is more complex than that).
If the length of the field i
on the current line is longer than the value stored in lval[i]
, the script will store the current length of the field in lval[i]
and the current line number (which is accessible through the "automatic" variable FNR
) into the array variable lpos
.
At the end of the file (END
condition), it will print the longest length and corresponding position for all columns. I use the construct for (i in lval)
which loops over all indices present in the array lval
, so I don't have to save the number of columns in an extra variable (as would be necessary for something like for (i=1;i<=ncols;i++)
- in the END
block, the concept of "number of fields" becomes somewhat ill-defined although in practice awk
will often use the corresponding values for the last line of the file when accessed).
Note that it is rarely necessary to call awk
in a shell loop; it can do most of the things you would need a loop for by itself.
As for the reason why your original attempt failed, you are trying to feed a shell variable ($i
) to an awk
script whose code is enclosed in single quotes (as is recommended), but the single quotes turn off the interpretation of shell variables (and even if not, it would not have worked like that).
i
is never assigned a value, so$i
is always$0
- hence you will get the lengths of the whole record at every iteration. But shell looping over an awk command is rarely a good option. – steeldriver Jul 15 '20 at 12:41$i
into awk, you can add-v i="$i"
. See for example external variable in awk – steeldriver Jul 15 '20 at 12:55