3

Can you tell me how to find the maximum length of characters in a given field?

For instance, with this input file:

s.no,name
1,ATM
35,money
63,back

The maximum length in field 1 is 2. So, I want the output to be:

s.no,name
01,ATM
35,money
63,back

Here, we just add the zeros before number if it is <2. Please help me.

1
  • s.no are 4 characters. Aren't your fields defined by commas? Are we supposed to skip the first line as a header? How do we know the max length? Should we first read the entire file and find the longest field?
    – terdon
    Mar 8 '14 at 15:37
4

First you need to find the maximum length. Comma is your field separator, and you need to ignore the first line:

len=$(awk -F, 'BEGIN{mn=0;} NR>1{n=length($1);mn=mn>n?mn:n;}END{print mn}' test.txt)

Now we use printf to expand the first field:

awk -F, 'NR==1{print $0};NR>1{ printf("%0'"$len"'d,",$1); for(i=2;i<=NF;i++)print($i); }' < test.txt

Note the single quotes end before "$len" to insert the field length and then they continue.

EDIT (thanks @dave_thompson_085 for a more elegant solution):

len=$(awk -F, 'BEGIN{mn=0} NR>1{n=length($1);mn=mn>n?mn:n;}END{print mn}' test.txt)
awk -F, -vOFS=, -vmn=$len 'NR>1{ $1=sprintf("%0*d",mn,$1)} 1' test.txt

where the last 1 means true and empty action means {print}.

8
  • To editor @terdon, on the less serious side: cats are not useless. They are fluffy and cute and help you incrementally update the command without the last argument being in the way :)
    – orion
    Mar 8 '14 at 16:06
  • 1
    The edit is fine. I'm just saying that when I create a oneliner with features that I'm less familiar with, I test smaller parts first and then build it part by part to see if it still works. Editing the last command from history is easier if you don't have to skip over a word every time. I just forgot to put the cat back in his box when I was finished :)
    – orion
    Mar 8 '14 at 16:14
  • 1
    Tsk, what would Schrodinger say? :)
    – terdon
    Mar 8 '14 at 16:15
  • 1
    @orion you can generally use <file.txt command_foo | command_bar rather than cat file.txt | command_foo | command_bar -- the < redirection doesn't have to go at the end of the command.
    – evilsoup
    Mar 8 '14 at 16:33
  • 1
    The for(i...)print($i) does the wrong thing if NF>2, so for the example data I would just use print($2). If you do need to handle more, easiest to use awk's default rebuild; also I would use printf %* instead of the tricky quoting, and the default print action; combining these: gawk -F, -vOFS=, -vmn=$len 'NR>1{$1=sprintf("%0*d",mn,$1}1' Mar 9 '14 at 13:12
2

If you just want to add a 0 if the first column is a single character, this will do:

sed -e 's/^.,/0&/' input.txt

In lines where the second character is a comma, it prepends a 0.

If the maximum length of your first column becomes 3 instead of 2, then you can do like this:

sed -e 's/^.,/00&/' -e 's/^..,/0&/' input.txt

Or, if you want to make this all dynamic, and pad as many zeros as necessary depending on the longest value in the first column, you could use this awk:

awk -F, 'NR == 1; NR > 1 { data[NR] = $0; w1[NR] = length($1); if (length($1) > max) max = length($1) } END { for (i=2; i<= NR; ++i) { w = max - w1[i]; if (w > 0) printf "%0*d", w, 0; print data[i] } }' input.txt

The same thing but expanded to multiple lines for readability, with comments:

awk -F, '
NR == 1  # the first line is the header, just print it as it is
NR > 1 {
    data[NR] = $0        # save the line
    w1[NR] = length($1)  # save the width of 1st field
    if (length($1) > max) max = length($1)  # update max length
}
END {  # pass 2: now that we know max length, print the lines
    for (i = 2; i <= NR; ++i) {
        w = max - w1[i]  # calculate the zeros we need to prepend
        if (w > 0) printf "%0*d", w, 0  # print w zeros, if necessary
        print data[i]    # print the saved line
    }
}' input.txt
3
  • Thanks Janos. its executed but it insert only one 0 (zero). if suppose 0012,ATM 3455,money 063,back.. like this.. we dont know exactly how many zero's to add. plz tel me Mar 9 '14 at 15:03
  • @suneelbabu.etl did you try the awk solution? That should work, dynamically detecting the max length.
    – janos
    Mar 9 '14 at 16:53
  • i tried janos, but it is also output came like this only.. plz tel me Mar 9 '14 at 17:46
0
awk '{if (length ($2)>max) max=length($2)} END {print max}' filename

The above command displays length of longest name column (i.e, $2=2nd column)

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.