views:

57

answers:

2

Starting with a string of an unspecified length, I need to make it exactly 43 characters long (front-padded with zeroes). It is going to contain IP addresses and port numbers. Something like:

### BEFORE
# Unfortunately includes ':' colon
66.35.205.123.80-137.30.123.78.52172:
### AFTER
# Colon removed.
# Digits padded to three (3) and five (5) 
# characters (for IP address and port numbers, respectively)
066.035.005.123.00080-137.030.123.078.52172  

This is similar to the output produced by tcpflow.

Programming in Bash. I can provide copy of script if required.
If it's at all possible, it would be nice to use a bash built-in, for speed. Is printf suitable for this type of thing?

+1  A: 

Yes, sounds like an excellent match for printf. You can probably use cut to split the incoming address into fields, which you can then feed back into printf to do the formatting.

Here's a quick sketch, it can certainly be improved to get the exact output format that you require:

#!/usr/bin/env bash

function format_address()
{
    printf "%03d.%03d.%03d.%03d.%05d" $(echo $1 | cut -d'.' --output-delimiter=' ' -f1-5)
}

for a in $(echo $1 | tr -d ':' | cut -d '-' --output-delimiter=' ' -f1,2)
do
    format_address $a
done
unwind
Nice. But the '-' must appear between the two sets: 066.035.005.123.00080-137.030.123.078.52172
Felipe Alvarez
+3  A: 

This uses IFS to split the address info into an array. Then printf saves the formatted result back into the original variable for further processing. Pure Bash - no external executables are used.

addr='66.35.205.123.80-137.30.123.78.52172:'
saveIFS=$IFS
IFS='.-:'
arr=($addr)
IFS=$saveIFS
printf -v addr "%03d.%03d.%03d.%03d.%05d-%03d.%03d.%03d.%03d.%05d" ${arr[@]}
do_something "$addr"

Edit:

Without using an array:

addr='66.35.205.123.80-137.30.123.78.52172:'
saveIFS=$IFS
IFS='.-:'
printf -v addr "%03d.%03d.%03d.%03d.%05d-%03d.%03d.%03d.%03d.%05d" $addr
IFS=$saveIFS
do_something "$addr"
Dennis Williamson
$IFS - you've helped me with that one more than once now DW :)
Felipe Alvarez
Accepted answer for using no outside executables.
Felipe Alvarez
This works. But I'd like to know why an array was used? Would a single variable with space-separated values _not_ do the job as well? Would it it conflict with `printf` in some way?
Felipe Alvarez
@Felipe: You can do it without the array. I'll post an edit that shows that.
Dennis Williamson