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:3
y los dígitos que tienen 5 dígitos deben cambiarse, s:5
y 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 -i
para 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";};