Analizar datos según el número de dígitos entre comillas

Analizar datos según el número de dígitos entre comillas

Tengo una gran cantidad de datos actualmente en el formato actual:

a:7:{i:0;s:4:"9999";i:1;s:4:"10000";i:2;s:4:"10001";i:3;s:4:"10002";i:4;s:4:"10003";i:5;s:4:"10004";i:6;s:4:"989";}

Los números que están dentro ""delante de ellos tienen s:4. Para los números que tienen 3 dígitos, esto debe cambiarse a s:3y los dígitos que tienen 5 dígitos deben cambiarse, s:5y así sucesivamente.

Los datos convertidos deberían verse así:

a:7:{i:0;s:4:"9999";i:1;s:5:"10000";i:2;s:5:"10001";i:3;s:5:"10002";i:4;s:5:"10003";i:5;s:5:"10004";i:6;s:3:"989";}

Cada cadena de datos {}está en su propia línea endata.txt

Respuesta1

Qué tal si

perl -pe 's/s:\d+:"(.*?)"/sprintf("s:%d:\"%s\"",length($1),$1)/ge'

Ex.

$ echo 'a:7:{i:0;s:4:"9999";i:1;s:4:"10000";i:2;s:4:"10001";i:3;s:4:"10002";i:4;s:4:"10003";i:5;s:4:"10004";i:6;s:4:"989";}' | 
    perl -pe 's/s:\d+:"(.*?)"/sprintf("s:%d:\"%s\"",length($1),$1)/ge'
a:7:{i:0;s:4:"9999";i:1;s:5:"10000";i:2;s:5:"10001";i:3;s:5:"10002";i:4;s:5:"10003";i:5;s:5:"10004";i:6;s:3:"989";}

Puede agregar -ipara realizar la sustitución en el archivo in situ.

Respuesta2

#!/usr/bin/env bash

IFS=';'

while read LINE
do

        set -- $LINE

        while [ "$1" ]
        do
                if [[ $1 =~ ^s:[0-9]+:\".*\"$ ]]; then
                        s=${1##*:}
                        printf 's:%d:%s%s' $((${#s}-2)) "$s" "$IFS"
                else
                        printf '%s%s' "$1" "$IFS"
                fi
                shift

        done
        printf '\n'

done < data.txt

Este script establece el separador de campos en el carácter de punto y coma y luego recorre las líneas de data.txt, dividiendo cada línea en campos separados en el delimitador de punto y coma. Para los campos que comienzan con s:###:"..."(para valores arbitrarios de ###y ...), el script calcula la longitud de la cadena entrecomillada y reformatea el campo usando ese valor de longitud y agregando un separador de campo final. Los campos que no coinciden con el formulario s:###:"..."se muestran palabra por palabra, agregando nuevamente el separador de campo final.

a:7:{i:0;s:4:"9999";i:1;s:5:"10000";i:2;s:5:"10001";i:3;s:5:"10002";i:4;s:5:"10003";i:5;s:5:"10004";i:6;s:3:"989";};

información relacionada