Reputation: 41
So here is my problem. How can I extract those strings into 3 variables with a bash script?
So out of this:
<key>GameDir</key> <string>C:/Program Files/</string> <key>GameEXE</key> <string>C:/Program Files/any.exe</string> <key>GameFlags</key> <string>-anyflag</string>
I want:
GameDir=C:/Program Files/
GameEXE=C:/Program Files/any.exe
GameFlags=-anyflag
Example Script:
echo GameDir
echo GameEXE
echo GameFlags
Example Output:
C:/Program Files/
C:/Program Files/any.exe
-anyflag
The order of the keys is not changing, only the strings itself. I am using OS X, so it needs to be a command that works out-of-the-box on OS X. Maybe this could work with sed?
Thanks Drakulix
Upvotes: 4
Views: 4768
Reputation: 15019
You could use /usr/libexec/PlistBuddy
for this, which seems to be included in OS X since at least 10.5 (man page). Example:
file="$HOME/yourfile"
/usr/libexec/PlistBuddy -c "Print" "$file"
And you could assign the vars you're interested in like this:
for var in GameDir GameEXE GameFlags ; do
val=$( /usr/libexec/PlistBuddy -c "Print $var" "$file" )
eval "export $var='$val'"
echo "$var = $val"
done
It seems more readable than bash/sed/awk regexes, and since it is a plist-specific tool, I presume it is reliable for extracting values. Just be aware that the keys are case-sensitive.
Upvotes: 8
Reputation: 343057
you can use awk, this works for multiline and multiple key, string values.
$ cat file
<key>GameDir</key> <string>C:/Program Files/
</string>
<key>GameEXE</key>
<string>C:/Program Files/any.exe
</string> <key>GameFlags</key> <string>-anyflag</string>
$ awk -vRS="</string>" '/<key>/{gsub(/<key>|<string>|\n| +/,"") ; sub("</key>","=") ;print}' file
GameDir=C:/ProgramFiles/
GameEXE=C:/ProgramFiles/any.exe
GameFlags=-anyflag
Use eval to create the variables
$ eval $(awk -vRS="</string>" '/<key>/{gsub(/<key>|<string>|\n| +/,"") ; sub("</key>","=") ;print}' file )
$ echo $GameDir
C:/ProgramFiles/
Upvotes: 0
Reputation: 360665
Assuming Bash version >= 3.2
string='<key>GameDir</key> <string>C:/Program Files/</string> <key>GameEXE</key> <string>C:/Program Files/any.exe</string> <key>GameFlags</key> <string>-anyflag</string>'
or
string=$(<file)
and
pattern='<key>([^<]*)</key>[[:blank:]]*<string>([^<]*)</string>[[:blank:]]*'
pattern=$pattern$pattern$pattern
[[ $string =~ $pattern ]] # extract the matches into ${BASH_REMATCH[@]}
for ((i=1; i<${#BASH_REMATCH[@]}; i+=2))
do
declare ${BASH_REMATCH[i]}="${BASH_REMATCH[i+1]}" # make the assignments
done
echo $GameDir # these were missing dollar signs in your question
echo $GameEXE
echo $GameFlags
Upvotes: 3