This thread is turning up some goodies.
Good shout hiran, I'd forgotten about propertree... I used it a little while back. Great tool. Fine for editing, but not programmable to do what's been asked for here IIRC.
Awk.. I love the example above from Commander_X, and I'll bookmark it as a good example. I wish I'd had cause to fall further into the awk rabbit hole. I use pinches of it it in pipelines for simple things such as printing the fourth, second, then first word from each line when e.g. parsing csv's in shell scripts, but am not fluent in it. The example above is far cleaner than my bash-smashery, and certainly easier to port across platforms. I'll bet there's less Gnu vs BSD divergence than with sed and grep.
The awk script as-is relies on the keys in the xml being alphabetically sorted, so economy MUST be above sun_distance, which is happily true in this case.. I had set out aiming to make it work regardless the order of keys in a system block, but when I noticed the rigid ordering I took advantage
So my script above is prone to the same potential failing upon adaption to other plists. It may have been simpler had I realised sooner.
I'd like to add to the heap of tools:
plistutil, a tool to convert from/to binary/xml plist formats. Available on many distros via apt get plistutil, or from
https://libimobiledevice.org. This is something propertree can do, but plistutil may be more useful as a command line tool when batch processing. A binary plist could be turned into xml, processed by whatever-script, then converted back, all without user interaction.
I agree that chunking it up into per-planet files would be a better approach to doing this sort of thing. Certainly so when using simple tools for batch edits like bash+sed/awk/grep. This would take some of the pain out of making a one-liner to test for a value and mangle a system accordingly, and thus simplify much of the potential line-ordering minefield.
So, here's a way to do that.
This works for me to split systems out to separate files from the planetinfo.plist. It adds zero padding to the system numbers to allow for easier sorting/searching/re-assembly.
Code: Select all
#!/bin/bash
# ! and % are absent in the plist, so I can use them as keys.
infile=~/GNUstep/Applications/Oolite/oolite.app/Resources/Config/planetinfo.plist
outdir=planets
mkdir -p "$outdir"
sed -E '
/^\s*"[0-9]+\s+[0-9]+"\s*=\s*\{/,/^\s*\}\s+$/{
s/$/!/g
}
' "$infile" | grep -e '\!$' -e '\%$' | tr -d '\n' |\
sed 's/\!\!/\!%/g' | \tr '%' '\n' |\
while read p ; do
s=$(
echo "$p" | sed -E '
s/^\s*"([0-9]+)\s+([0-9]+)"\s*=\s*\{.*$/\1-\2/
'
)
x=${s%-*}
y=$[ ${s#*-} +1000 ] ; y=${y#1} # add leading zeroes
echo -en "\rSystem ${x}-${y} "
dat=$(
echo "$p" | tr '!' '\n' | tr -d '%' > "$outdir/p_${x}-${y}.frag"
)
done
echo #reset prompt
I manually chopped the top and tail from the xml, I'd suggest putting them in the output directory as a_top and z_tail. Then you can simply cat * > output.plist or whatever to re-assemble. The filenames should be just fine for wildcard jiggery-pokery.
Here's the top of the directory:
Code: Select all
$ ls planets/ | head -n 4
a_top
p_0-000.frag
p_0-001.frag
p_0-002.frag
p_0-003.frag
On my laptop it took 14 seconds to run. Considering how clunky the script is, I'll take that. Ripping the plist apart is not likely to be done very often, so it's not worth optimising.
Re-assembly is somewhat faster:
Code: Select all
$ time cat planets/* > newplanetinfo.plist
real 0m0.060s
user 0m0.024s
sys 0m0.035s
Here's a zip with the script and broken down planetinfo.plist as 2050 files in a directory
chunky.zip. The link will expire in 30 days.
I know there are going to be more succinct ways to do this, but I like cobbling stuff together as one-liners in bash, then editing them into tools.
'd be happy to see a better, cross-platform method appear here.