From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27576 invoked by alias); 27 Feb 2011 21:02:12 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 28806 Received: (qmail 8752 invoked from network); 27 Feb 2011 21:01:55 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <110227130132.ZM4792@torch.brasslantern.com> Date: Sun, 27 Feb 2011 13:01:32 -0800 In-reply-to: Comments: In reply to Rocky Bernstein "typeset -p output gives shows variables which can't be read back in" (Feb 27, 6:44am) References: X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: Re: typeset -p output gives shows variables which can't be read back in MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Feb 27, 6:44am, Rocky Bernstein wrote: } } A little bit of context of why I am doing this. Recently in the zsh } debugger I've added the ability to go into a nested zsh, and often one } wants the existing environment of the debugged program preserved in } this nested zsh. You're kind of doomed here from the start. If the debugger is inside a shell function, for example, you're never going to get scoping back. } I would like to save to a file shell variables so that I can run a } nested zsh and then read these back in. It is becoming a bit of a } challenge because this in the output: } } typeset -i10 -r !=0 Hm, I'm a bit surprised the '!' isn't quoted there; but the real issue is that you get "not an identifier" or the like for a number of those, and "can't change type" for ones that come from zsh/parameter, plus a few "read-only variable" complaints. } typeset -ar '*' Hmm, strange. That one does NOT give "not an identifier" ... } *=() ... but that of course bombs with a globbing error. } Failing a better solution, I think what I'll have to do is store IFS='' } typeset -p into an array and check each item of the array. The zsh/parameter module $parameters hash already tells you nearly all you need to know. Something like this: () { local param type for param type in "${(kv@)parameters}" do case "$type" in (*local*) continue;; # Skip loop variables (*export*) continue;; # No need to dump/restore if exported? (*special*) continue;; # Maintained by the shell (*readonly*) continue;; (*) typeset -p "$param";; esac done } You can avoid zsh/parameter by parsing the output of "typeset +m +": () { local param type description typeset +m + | while read -A description do param="${description[-1]}" description[-1]=() if (( ${#description} )) then type="${description[*]}" else type=scalar fi case "$type" in (*local*) continue;; # Skip loop variables (*export*) continue;; # No need to dump/restore if exported? (*readonly*) continue;; (*) typeset -p "$param";; esac done } However, that doesn't let you catch "special" parameters, though you can still filter the readonly subset. Note both of these techniques still miss things like: typeset -T foo FOO I.e., there's no way to discover by examination that an array and scalar have been tied together. } But then we come to the typeset -ar '*' line which I guess flows onto the } next line. Not exactly "flows", but for arrays and associative arrays (hashes) the value can't be supplied in the typeset command, so an assignment line is needed. Also you may have to be careful with the order of assignments when you read the file back in. Some assignments to special variables (like to the "options" hash) might change shell behavior in unexpected ways.