Luke Luke - 3 days ago 6
Bash Question

Iterate an array in a shell script to save its values in a .plist and a .db

This shell script allows to programmatically save text replacements for macOS, on both

GlobalPreferences.plist
and
UserDictionary.db
.

date=$(date +%s)
while read -r replace with; do
plist+="{on=1;replace=\"$replace\";with=\"$with\";},"
sql+="INSERT INTO 'ZUSERDICTIONARYENTRY' VALUES($((++i)),1,1,0,0,0,0,$date,NULL,NULL,NULL,NULL,NULL,\"$with\",\"$replace\",NULL);"
done < <(sed 's/\\/\\\\/g;s/"/\\"/g' ~/replacements.txt)
sqlite3 ~/Library/Dictionaries/CoreDataUbiquitySupport/$USER~*/UserDictionary/local/store/UserDictionary.db "delete from ZUSERDICTIONARYENTRY;$sql"
defaults write -g NSUserDictionaryReplacementItems "(${plist%?})"


How can I customize it so that it can read a previously declared array, instead of a
~/replacements.txt
external file?

Answer

Assuming (and these are large and unfounded assumptions, necessary due to the vagueness of the question) that your array contains one entry per line of the input file:


Replace

sed 's/\\/\\\\/g;s/"/\\"/g' ~/replacements.txt

with:

printf '%s\n' "${replacements[@]}" | sed 's/\\/\\\\/g;s/"/\\"/g'

To be clear, this is assuming a numerically-indexed array. For instance, you could generate such an array from your replacements.txt with:

# in bash 4.0 or newer
mapfile -t replacements <~/replacements.txt

...or:

# in bash 3.x or newer
replacements=( )
while IFS= read -r line; do replacements+=( "$line" ); done <~/replacements.txt
Comments