Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need have put 0 on the results of my grep so my script format will be fine and i don't have any idea how to do it. here's my grep result :

261 : 261 = 0 | 1192 : 1184 = 8 | 
283 : 283 = 0 | 666 : 659 = 7 | 
267 : 267 = 0 | 631 : 620 = 11 |  
283 : 283 = 0 | 787 : 781 = 6 | 
278 : 279 = -1 | 963 : 957 = 6 |

i wish to output something like this :

261 : 261 = 000  | 1192 : 1184 = 0008 |   
283 : 283 =  000  | 0666 : 0659 = 0007 | 
267 : 267 =  000  | 0631 : 0620 = 0011 | 
283 : 283 =  000  | 0787 : 0781 = 0006 | 
278 : 279 = -001  | 0963 : 0957 = 0006 |

to get that result here is my script :

count100=`grep -ach "0100 $GivenBIN" $line`
count110=`grep -ach "0110 $GivenBIN" $line`
filename=`echo $line | awk -F"/" '{print $NF}'`
echo -e "$filename     $count100 : $count110 = $ans1| $count220 : $count230 = $ans4 |" 
share|improve this question

3 Answers 3

Based on your sample input and output, I gather that

  • columns of numbers are always separated by whitespace;
  • you want to format each numeric column to a known fixed width;
  • you want the same number of digits in each line in each given column;
  • one column has a leading sign (space or -).

This translates to the following awk script, which applies a printf format to each numeric column.

awk 'BEGIN {
    widths[1]=widths[3]=3;
    widths[5]=" 4";
    widths[7]=widths[9]=widths[11]=4
}
{
    for (i in widths) $i = sprintf("%0" widths[i] "d", $i);
    print
}'
share|improve this answer

You could use the printf command: its first argument is a format string, followed by other arguments that will be inserted into the format string, one per format specifier.

The format specifier for printing a string is %s; an integer number is printed with %d; you can optionally specify a total number of digits (e.g., 4) and a leading 0 for padding with the format %04d; if you want a sign to be always printed, add a + after the % character, if you want a sign to be printed only if the number is negative, follow % by a space character () instead. Also, you must terminate the format string with \n to print a final end-of-line like echo normally does.

See the printf(3) man page for the complete listing.

So, for instance:

count100=grep -ach "0100 $GivenBIN" $line
count110=grep -ach "0110 $GivenBIN" $line
filename=echo $line | awk -F"/" '{print $NF}'
printf '%s %d : %d = % 03d | %s : %d = %04d\n' "$filename" "$count100" "$count110" "$ans1" #...

will print the lines in the format you want.

share|improve this answer
    
I think he's after 3 digits for all items in the first group, and 4 digits for all in the second group... based on his preferred output, eg the last line ... but that is not as simple as the above command, because of negative values..eg, printf '%04d', -1 returns -001 (not -0001) –  Peter.O May 29 '11 at 18:50
    
@fred thanks for pointing this out; I've missed the sign in the sample output. I've adjusted the specifier. –  Riccardo Murri May 30 '11 at 16:15

This is 4 sed expressions; long but simple
It adds an excess of leading zeroes, and then trims the numbers to 3 and 4 long for the left and right sides respectively.
It is hard to construct something like this in a single line, but it is quite easy when it is laid out over many lines as shown in the last code section...
printf may be a solution, but it is not be as simple as I first thought, because of negative numbers, ie. your requirement is that all the negative numbers have the same number of digits as the positive numbers..
...so I'm throwing in this sed method because it does work, but there may be more simple solutions...

sed -r -e "s/^([0-9]+)( : )([0-9]+)( = )(-)?([0-9]+)( )/00\1\200\3\4\500\6\7/" -e "s/0*([0-9][0-9][0-9])( : )0*([0-9][0-9][0-9])( = )(-)?0*([0-9][0-9][0-9])( )/\1\2\3\4\5\6\7/" -e "s/( )([0-9]+)( : )([0-9]+)( = )(-)?([0-9]+)( .)$/\1000\2\3000\4\5\6000\7\8/" -e "s/( )0*([0-9][0-9][0-9][0-9])( : )0*([0-9][0-9][0-9][0-9])( = )(-)?0*([0-9][0-9][0-9][0-9])( .)$/\1\2\3\4\5\6\7\8/" \
<<'EOF'
261 : 261 = 0 | 1192 : 1184 = 8 |
283 : 283 = 0 | 666 : 659 = 7 |
267 : 267 = 0 | 631 : 620 = 11 |
283 : 283 = 0 | 787 : 781 = 6 |
278 : 279 = -1 | 963 : 957 = 6 |
278 : 279 = -1 | 963 : 954 = -1 |
EOF

Here is the output

261 : 261 = 000 | 1192 : 1184 = 0008 |
283 : 283 = 000 | 0666 : 0659 = 0007 |
267 : 267 = 000 | 0631 : 0620 = 0011 |
283 : 283 = 000 | 0787 : 0781 = 0006 |
278 : 279 = -001 | 0963 : 0957 = 0006 |
278 : 279 = -001 | 0963 : 0954 = -0001 |

Here is a more readable version of the sed expressions.

sed -r \
-e "s/^\
([0-9]+)( : )\
([0-9]+)( = )(-)?\
([0-9]+)( )\
/00\1\200\3\4\500\6\7/" \
-e "s/\
0*([0-9][0-9][0-9])( : )\
0*([0-9][0-9][0-9])( = )(-)?\
0*([0-9][0-9][0-9])( )\
/\1\2\3\4\5\6\7/" \
-e "s/( )\
([0-9]+)( : )\
([0-9]+)( = )(-)?\
([0-9]+)( .)$\
/\1000\2\3000\4\5\6000\7\8/" \
-e "s/( )\
0*([0-9][0-9][0-9][0-9])( : )\
0*([0-9][0-9][0-9][0-9])( = )(-)?\
0*([0-9][0-9][0-9][0-9])( .)$\
/\1\2\3\4\5\6\7\8/" \
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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