bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

printf builtin's %q format specifier -- Tilde not escaped?


From: Jens Stimpfle
Subject: printf builtin's %q format specifier -- Tilde not escaped?
Date: Tue, 7 Aug 2012 15:37:18 +0200
User-agent: Mutt/1.5.20 (2009-06-14)

Bash's printf builtin has a %q format specifier, which, according to the
documentation, "causes printf to output the corresponding argument in a
format that can be reused as shell input".

My intuitive interpretation of "can be reused as shell input" could be
approximated by "can be used as a substring of a shellscript so that it
is parsed as a single argument to a command, equal to the input
argument".

In other words, %q should be the inverse operation to shell parsing, in
the sense that, for a concrete example,

        eval "echo $(printf %q ANY)"

should be equal to

        echo ANY

where ANY is an arbitrary sequence of characters, with the constraint
that it must parse to a single word.

What seems wrong to me is that the tilde character (~) is not escaped

        $ eval "echo $(printf %q '~')"
        /home/jens
        $ echo '~'
        ~

In the bash source, tilde-escaping code already exists, but it is
commented out. How about turning this back on? Or am I just
misunderstanding what %q should do?


Have a nice day
-Jens Stimpfle


----- From lib/sh/shquote.c ------

char *
sh_backslash_quote (string)
     char *string;
{
  int c;
  char *result, *r, *s;

  result = (char *)xmalloc (2 * strlen (string) + 1);

  for (r = result, s = string; s && (c = *s); s++)
    {
      switch (c)
        {
        case ' ': case '\t': case '\n':         /* IFS white space */
        case '\'': case '"': case '\\':         /* quoting chars */
        case '|': case '&': case ';':           /* shell metacharacters
*/
        case '(': case ')': case '<': case '>':
        case '!': case '{': case '}':           /* reserved words */
        case '*': case '[': case '?': case ']': /* globbing chars */
        case '^':
        case '$': case '`':                     /* expansion chars */
        case ',':                               /* brace expansion */
          *r++ = '\\';
          *r++ = c;
          break;
#if 0
        case '~':                               /* tilde expansion */
          if (s == string || s[-1] == '=' || s[-1] == ':')
            *r++ = '\\';
          *r++ = c;
          break;

        case CTLESC: case CTLNUL:               /* internal quoting
characters */
          *r++ = CTLESC;                        /* could be '\\'? */
          *r++ = c;
          break;
#endif

        case '#':                               /* comment char */
          if (s == string)
            *r++ = '\\';
          /* FALLTHROUGH */
        default:
          *r++ = c;
          break;
        }
    }

  *r = '\0';
  return (result);
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]