How to escape single quotes from a string caused by single quotes

Keywords: shell Unix

Suppose you have a Bash alias for example:

alias rxvt='urxvt'

Good results.

However:

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

It will not work, nor will it:

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

So, once the quotes are escaped, how do you eventually match the start and end quotes in the string?

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

It looks awkward, though if you allow them to be concatenated, it will represent the same string.

#1st floor

I didn't see this entry on his blog (link?)But according to gnu reference manual :

Including characters in single quotation marks ('') preserves the literal value of each character within the quotation marks.Even a backslash before a single quotation mark cannot cause a single quotation mark between single quotations.

So bash can't understand:

alias x='y \\'z '

However, if caused by double quotation marks, you can do the following:

alias x="echo \'y "
> x
> 'y

#2nd floor

If you do want to use single quotation marks on the outside, remember that you can paste both at the same time.Example:

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

How does'''mean only':

  1. 'End with single quotation marks.
  2. "Use double quotation marks to start the second quotation mark.
  3. 'Reference character.
  4. "Use double quotation marks to end the second quotation mark.
  5. 'Use single quotation marks to cause the third quotation mark.

If you do not place any spaces between (1) and (2) or between (4) and (5), Shell interprets the string as a long word.

#3rd floor

I don't specifically address quotation issues because sometimes it makes sense to consider alternatives.

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

You can call it:

rxvt 123456 654321

The idea is that you can alias this now without worrying about quotation marks:

alias rxvt='rxvt 123456 654321'

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

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

You can call it:

rxvt '#123456' '#654321'

Then, of course, the alias is:

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

(Bad, I think I did solve the problem:)

#4th floor

I always replace each embedded single quotation mark with a sequence only:'\'(that is, quotation backslash quotation marks), which closes the string, appends the escaped single quotation mark, and reopens the string.

I often whip a quote function in my Perl script to do this for me.The steps will be:

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

This handles almost everything.

Life becomes more interesting when eval is introduced into shell scripts.Basically you have to re-quote everything!

For example, create a Perl script named quotify that contains the following statements:

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

Then use it to generate a properly referenced string:

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

Result:

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

You can then copy/paste it into the alias command:

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

(If you need to insert a command into the evaluation, run quotify again:

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

Result:

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

You can copy/paste it into the assessment:

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

#5th floor

Because Bash 2.04 The syntax $'string'(not'string'); warning: do not confuse with $('string') is another reference mechanism that allows ANSI C-like escape sequences And expanded to single quote version.

Simple examples:

  $> 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 escape sequences work as expected:

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

The following documents are copied and pasted in man bash (version 4.4):

Words in the $'string'form are specially processed.The word expands to a string and replaces the backslash escape character as specified in the ANSI C standard.The backslash escape sequence (if present) is 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 result is a single quotation mark, as if there were no dollar signs.

For more details, see the Quotes and Escapes: Strings similar to ANSI C .Also note that "Bash Change" Files ( Overview here ) Many changes and bug fixes related to the $'string'reference mechanism have been mentioned.

According to unix.stackexchange.com, How do I use special characters as common characters? It should work in bash, zsh, mksh, ksh93 and FreeBSD and busybox sh (with some variations).

Posted by shlomikalfa on Sat, 14 Dec 2019 21:00:15 -0800