#! /bin/sh ## This sed(1) script takes key/value pairs in tripe-admin(5) format as ## input; it writes sh(1) variable assignments as output. The idea is that ## you can say ## ## eval $(tripectl algs | sed "$keysubst") ## ## and have shell variables set from the output of the command. The shell ## variable names are worked out from the key names, with sequences of ## nonalphanumerics replaced by single underscores. Quoting is handled ## correctly, both on input and output. ## ## Theory of operation: firstly, ! and @ characters in the input are replaced ## by !e and !a respectively; this is a reversible transformation, which we ## undo at the end. We now know that the input does not contain @. We use a ## string of the form [lr][nqQ]@ as a cursor to move across the input from ## left to right. The letters on the left of the @ are state markers: l ## means left of =, r means right; n means not in quotes; q means single- ## quoted; Q means double-quoted. ## ## This is a particularly awful hack. I'm so sorry. keysubst=' ## Initial transformation. s/!/!e/g'$p' s/@/!a/g'$p' ## Initial state: left-hand side, not quoted s/^/ln@/'$p' :loop ## Reached the end: exit. /@$/ b end ## Enter or leave quoted state as necessary. s/\(.\)n@'\''/\1q@/'$p' s/\(.\)n@"/\1Q@/'$p' s/\(.\)q@'\''/\1n@/'$p' s/\(.\)Q@"/\1n@/'$p' t loop ## Leave backslashed things alone. /\(..\)@\\/ { s//\1@/ b lit } ## Unquotes spaces delimit key/value pairs. s/\(rn\)@[ ]\+/'\'' ln@/'$p' ## An = sign separates left and right sides. s/l\(.\)@=/='\''r\1@/'$p' ## Single quotes on the right-hand side need special care. t loop s/r\(.\)@'\'/\''\\'\'\''r\1@/'$p' ## Sequences of alphanumerics are always easy. s/\(..\)@\([[:alnum:]]\+\)/\2\1@/'$p' :lit ## Convert bad left-hand-side characters to underscores. t loop s/l\(.\)@\(!.\|[^=![:alnum:]]\)\+/_l\1@/'$p' ## Convert sequences of nonproblematic right-hand-side characters. t loop s/\(r.\)@\([^ '\''"`]\+\)/\2\1@/'$p' ## And anything else is probably OK. s/\(..\)@\(.\)/\2\1@/'$p' b loop :end ## Unquote the end appropriately. s/r.@/'\''/'$p' s/..@//'$p' ## And undo the initial transformation. s/!a/@/g'$p' s/!e/!/g'$p' ' sed "$keysubst"