How to escape single quotes within single quoted strings

前端 未结 23 2151
说谎
说谎 2020-11-21 06:20

Let\'s say, you have a Bash alias like:

alias rxvt=\'urxvt\'

which works fine.

However:



        
相关标签:
23条回答
  • 2020-11-21 06:58

    I'm not specifically addressing the quoting issue because, well, sometimes, it's just reasonable to consider an alternative approach.

    rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }
    

    which you can then call as:

    rxvt 123456 654321
    

    the idea being that you can now alias this without concern for quotes:

    alias rxvt='rxvt 123456 654321'
    

    or, if you need to include the # in all calls for some reason:

    rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }
    

    which you can then call as:

    rxvt '#123456' '#654321'
    

    then, of course, an alias is:

    alias rxvt="rxvt '#123456' '#654321'"
    

    (oops, i guess i kind of did address the quoting :)

    0 讨论(0)
  • 2020-11-21 06:59

    in addition to @JasonWoof perfect answer i want to show how i solved related problem

    in my case encoding single quotes with '\'' will not always be sufficient, for example if a string must quoted with single quotes, but the total count of quotes results in odd amount

    #!/bin/bash
    
    # no closing quote
    string='alecxs\'solution'
    
    # this works for string
    string="alecxs'solution"
    string=alecxs\'solution
    string='alecxs'\''solution'
    

    let's assume string is a file name and we need to save quoted file names in a list (like stat -c%N ./* > list)

    echo "'$string'" > "$string"
    cat "$string"
    

    but processing this list will fail (depending on how many quotes the string does contain in total)

    while read file
      do
        ls -l "$file"
        eval ls -l "$file"
    done < "$string"
    

    workaround: encode quotes with string manipulation

    string="${string//$'\047'/\'\$\'\\\\047\'\'}"
    
    # result
    echo "$string"
    

    now it works because quotes are always balanced

    echo "'$string'" > list
    while read file
      do
        ls -l "$file"
        eval ls -l "$file"
    done < list
    

    Hope this helps when facing similar problem

    0 讨论(0)
  • 2020-11-21 07:01

    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 ':

    1. ' End first quotation which uses single quotes.
    2. " Start second quotation, using double-quotes.
    3. ' Quoted character.
    4. " End second quotation, using double-quotes.
    5. ' 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.

    0 讨论(0)
  • 2020-11-21 07:01

    Both versions are working, either with concatenation by using the escaped single quote character (\'), or with concatenation by enclosing the single quote character within double quotes ("'").

    The author of the question did not notice that there was an extra single quote (') at the end of his last escaping attempt:

    alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
               │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
               └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                          ┊┊         ┊┊       ┊┊         ┊┊│
                          ┊┊         ┊┊       ┊┊         ┊┊│
                          └┴─────────┴┴───┰───┴┴─────────┴┘│
                              All escaped single quotes    │
                                                           │
                                                           ?
    

    As you can see in the previous nice piece of ASCII/Unicode art, the last escaped single quote (\') is followed by an unnecessary single quote ('). Using a syntax-highlighter like the one present in Notepad++ can prove very helpful.

    The same is true for another example like the following one:

    alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
    alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'
    

    These two beautiful instances of aliases show in a very intricate and obfuscated way how a file can be lined down. That is, from a file with a lot of lines you get only one line with commas and spaces between the contents of the previous lines. In order to make sense of the previous comment, the following is an example:

    $ cat Little_Commas.TXT
    201737194
    201802699
    201835214
    
    $ rc Little_Commas.TXT
    201737194, 201802699, 201835214
    
    0 讨论(0)
  • 2020-11-21 07:01

    Since one cannot put single quotes within single quoted strings, the simplest and most readable option is to use a HEREDOC string

    command=$(cat <<'COMMAND'
    urxvt -fg '#111111' -bg '#111111'
    COMMAND
    )
    
    alias rxvt=$command
    

    In the code above, the HEREDOC is sent to the cat command and the output of that is assigned to a variable via the command substitution notation $(..)

    Putting a single quote around the HEREDOC is needed since it is within a $()

    0 讨论(0)
提交回复
热议问题