現在、現在の形式で大量のデータがあります:
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";}
""
それらの前の数字にはが付いていますs:4
。3 桁の数字の場合は に変更しs:3
、5 桁の数字の場合は に変更しますs:5
。
変換されたデータは次のようになります。
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";}
各データ文字{}
列は、data.txt
答え1
いかがでしょうか
perl -pe 's/s:\d+:"(.*?)"/sprintf("s:%d:\"%s\"",length($1),$1)/ge'
元。
$ 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";}
追加する-i
と、ファイル上でその場で置換を実行できます。
答え2
#!/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
このスクリプトは、フィールド区切り文字をセミコロン文字に設定し、 の行を反復処理してdata.txt
、各行をセミコロン区切り文字で個別のフィールドに分割します。 で始まるフィールド(とs:###:"..."
の任意の値) の場合、スクリプトは引用符で囲まれた文字列の長さを計算し、その長さの値を使用してフィールドを再フォーマットし、末尾にフィールド区切り文字を追加します。形式に一致しないフィールドは、そのまま出力され、末尾にフィールド区切り文字が再度追加されます。###
...
s:###:"..."
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";};