Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm trying to write a function, I'll call it escape, that will behave like this:

% IFS=$' \t\n\000'
% escape FOO $IFS
FOO=$' \t\n\000'

In other words, escape takes two arguments, and then, taking the first one to be a variable name, it prints out a line a zsh source code in which a variable of that name is assigned a $''-quoted, "canonically print-escaped" string, such that, upon evaluating this line of source code, the variable named by the the first argument will have the second argument as its value. (I'm sure that was as clear as mud, so I'll give more examples of how escape is supposed to behave at the end of this post.)

Here's an incomplete implementation of the escape function:

escape () {
    local varname=$1
    local value="$2"
    print -n "$varname=\$'"
    # ???
    print "'"
}

The missing part (indicated by ???) is where the contents of $value are "canonically print-escaped". The qualifier "canonical" is necessary because there are many characters for which there are at least a couple of representations that print will recognize them as. For example, print knows \n also as \012 and as \C-J. In this case, \n is the canonical form. In general, the standard escape sequences \n, \r, \t, etc. are the canonical forms for their corresponding characters. The standard display form of printable ASCII characters (e.g. A, =, 9) are canonical. For the remaining characters, if there's a choice of representation, I'd pick the octal form as the canonical one (at least up to \177; I'm not sure of how $'' deals with higher codes), but this preference is not strong.

Of course, I'm not looking to see code to implement this functionality "from scratch", as it were. Rather, I'm hoping that a utility already exists to perform this translation from bytes to a print-escaped text representation.

Any pointers would be much appreciated!


Here are some more examples of escape in action (hypothetically):

% escape HELLO $( echo 'hello world' )
HELLO=$'hello world\n'
% escape SUBSEP $( perl -e 'print $;' )
SUBSEP=$'\034'
% abc=$'\141\012\142\012\143\012'
% print -n $abc
a
b
c
% escape ABC $abc
ABC=$'a\nb\nc\n'
share|improve this question
add comment

1 Answer 1

up vote 2 down vote accepted

I think ing for the q parameter expansion flag, specifically the qqqq variant.

FOO=${(qqqq)IFS}

So you can write your function this way (using the P flag to expand the parameter whose name is $2):

escape () {
  print -r -- "$1=${(Pqqqq)2}"
}
share|improve this answer
    
Thanks, but, sorry, I fail to see the relevance of your answer to my question. As I explicitly stated, I want the output of escape FOO $IFS (with $IFS set as in my original post) to be the string "FOO=$' \t\n\000'", verbatim, and not the string "FOO=${(qqqq)IFS}", nor the string "FOO=" followed by the string that ${(qqqq)IFS} gets expanded to (which is not easy to reproduce in a comment but is nothing remotely like the string "$' \t\n\000'"). –  kjo Apr 24 '12 at 13:52
    
Sorry, there's a bug in the stackexchange software that causes a space to be lost in the first appearance of the substring "$' \t\n\000'" in my previous comment. –  kjo Apr 24 '12 at 13:58
    
@kjo I told you the main feature you would use to implement the escape function, I didn't think implementing the function itself was part of the difficulty. But there you go, here's an escape function. –  Gilles Apr 24 '12 at 17:20
    
No, what I was missing was the -r flag to print, without which your original answer is not useful. Thanks. –  kjo Apr 25 '12 at 2:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.