Experiència interessant amb sed on descobreixo que els bucles són permesos!

Cas d’ús

Parlant amb un company, em presenta la següent situació:

Tenim un nombre a l’estil 12345678.12 i volem que ens insereixi els grups de milers (amb un caràcter de coma) cada tres dígits segons la notació habitual. Requeriment: s’ha de fer amb línia d’ordres i amb l’ordre sed.

El problema és que, ho pensi com ho pensi, no trobo la manera de codificar-ho en una única sentència de sed sense fer bucles.

Fer la incorporació de l’últim punt de milers és fàcil. Només cal buscar un bloc de 4 dígits numèrics consecutius abans d’un punt de decimal o milers, i inserir la coma de milers entre el primer i el segon. Quelcom això:

echo "1234567890.12" | sed -E 's/([0-9])([0-9]{3,3}[.,])/\1,\2/g'

El resultat obtingut és 1234567,890.12.

Però per poder fer la conversió de tota la cadena s’hauria d’implantar un bucle que executi aquest procés mentre quedin blocs de 4 dígits seguits… Lleig!

La solució l’he trobada descobrint que sed accepta un pseudo-llenguatge de programació que inclou bucles en l’expressió a executar!!!

El format d’un bucle és així:

: etiqueta
/condició/ {
    ordre
    ordre
    ...
    b etiqueta
}

La directiva b és la que força que es torni a l’etiqueta inicial, fent un bucle on es valida la condició indicada.

En el cas presentat, la condició és que quedin blocs de 4 dígits seguits. Per tant, la solució a aquest repte és la següent:

echo "1234567890.12" | sed -E '
    :loop
    /[0-9]{4,4}/ {
        s/([0-9])([0-9]{3,3}[.,])/\1,\2/g
        b loop
    }
'

El resultat és ara el desitjat: 1,234,567,890.12.

Repte resolt!

Fonts d’informació addicionals: