How to escape single quotes within single quoted strings?

Let's say, you have a bash alias like:

alias rxvt='urxvt'

which works fine.

However:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

won't work, and neither will:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

So how do you end up matching up opening and closing quotes inside a string once you have escaped quotes?

alias rxvt='urxvt -fg'''#111111''' -bg '''#111111'''

seems ungainly although it would represent the same string if you're allowed to concatenate them like that.


If you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

Explanation of how '"'"' is interpreted as just ' :

  • ' End first quotation which uses single quotes.
  • " Start second quotation, using double-quotes.
  • ' Quoted character.
  • " End second quotation, using double-quotes.
  • ' Start third quotation, using single quotes.
  • If you do not place any whitespaces between (1) and (2), or between (4) and (5), the shell will interpret that string as a one long word.


    I always just replace each embedded single quote with the sequence: ''' (that is: quote backslash quote quote) which closes the string, appends an escaped single quote and reopens the string.


    I often whip up a "quotify" function in my Perl scripts to do this for me. The steps would be:

    s/'/'''/g    # Handle each embedded quote
    $_ = qq['$_']; # Surround result with single quotes.
    

    This pretty much takes care of all cases.

    Life gets more fun when you introduce eval into your shell-scripts. You essentially have to re-quotify everything again!

    For example, create a Perl script called quotify containing the above statements:

    #!/usr/bin/perl -pl
    s/'/'''/g;
    $_ = qq['$_'];
    

    then use it to generate a correctly-quoted string:

    $ quotify
    urxvt -fg '#111111' -bg '#111111'
    

    result:

    'urxvt -fg '''#111111''' -bg '''#111111''''
    

    which can then be copy/pasted into the alias command:

    alias rxvt='urxvt -fg '''#111111''' -bg '''#111111''''
    

    (If you need to insert the command into an eval, run the quotify again:

     $ quotify
     alias rxvt='urxvt -fg '''#111111''' -bg '''#111111''''
    

    result:

    'alias rxvt='''urxvt -fg '''''''''#111111''''''''' -bg '''''''''#111111'''''''''''''
    

    which can be copy/pasted into an eval:

    eval 'alias rxvt='''urxvt -fg '''''''''#111111''''''''' -bg '''''''''#111111'''''''''''''
    

    Since Bash 2.04 syntax $'string' (instead of just 'string' ) is another quoting mechanism which allows ANSI C-like escape sequences and do expansion to single-quoted version.

    Simple example:

      $> echo $'aa'bb'
      aa'bb
    
      $> alias myvar=$'aa'bb'
      $> alias myvar
      alias myvar='aa'''bb'
    

    In your case:

    $> alias rxvt=$'urxvt -fg '#111111' -bg '#111111''
    $> alias rxvt
    alias rxvt='urxvt -fg '''#111111''' -bg '''#111111''''
    

    Common escaping sequences works as expected:

    '     single quote
    "     double quote
         backslash
    n     new line
    t     horizontal tab
    r     carriage return
    

    Below is copy+pasted related documentation from man bash (version 4.4):

    Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:

        a     alert (bell)
        b     backspace
        e
        E     an escape character
        f     form feed
        n     new line
        r     carriage return
        t     horizontal tab
        v     vertical tab
             backslash
        '     single quote
        "     double quote
        ?     question mark
        nnn   the eight-bit character whose value is the octal 
               value nnn (one to three digits)
        xHH   the eight-bit character whose value is the hexadecimal
               value HH (one or two hex digits)
        uHHHH the Unicode (ISO/IEC 10646) character whose value is 
               the hexadecimal value HHHH (one to four hex digits)
        UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
                   is the hexadecimal value HHHHHHHH (one to eight 
                   hex digits)
        cx    a control-x character
    

    The expanded result is single-quoted, as if the dollar sign had not been present.


    See Quotes and escaping: ANSI C like strings on bash-hackers.org wiki for more details. Also note that "Bash Changes" file (overview here) mentions a lot for changes and bug fixes related to the $'string' quoting mechanism.

    According to unix.stackexchange.com How to use a special character as a normal one? it should work (with some variations) in bash, zsh, mksh, ksh93 and FreeBSD and busybox sh.

    链接地址: http://www.djcxy.com/p/1678.html

    上一篇: 如何递归计算目录中的所有代码行?

    下一篇: 如何在单引号字符串中转义单引号?