In a shell script I would like to quote this string of special characters \'%"\"'\ How do I escape the quotes/backslashes inside the string ?
If you use single quotes around the whole string, then the only thing you need to worry about is replacing every ' with '"'"':
$ string='\'"'"'%"\"'"'"'\'
$ echo "$string"
\'%"\"'\
This means:
' close the previous single-quoted string
"'" a new double-quoted string, containing a single quote
' open a new single-quoted string
The shell concatenates adjacent strings, so you get a single quote where you want it. You can replace the middle part by \' but personally I think that's more confusing!
Related
I have to implement a minishell written in C for my school homework,and I am currently working on the parsing of the user input and I have a question regarding single quote and double quote.
How are they parsed, I mean many combo are possible as long as there is more than two single quotes / double quote.
Let’s say I have : ""hello"".
If I echo this the bash output would be hello, is this because bash interpreted "hello" inside "" or because bash interpreted this as : "" then hello "".
How does bash parse multiple chained quotes :
" "Hello" " : let’s say a = Hello. Does bash sees "a" or bash see ""a""
Bash parses single- and double-quotes slightly differently. Single-quotes are simpler, so I'll cover them first.
A single-quoted string (or single-quoted section of a string -- I'll get to that) runs from a single-quote to the next single-quote. Anything other than a single-quote (including double-quotes, backslashes, newlines, etc) is just a literal character in the string. But the next single-quote ends the single-quoted section. There is no way to put a single-quote inside a single-quoted string, because the next single-quote will end the single-quoted section.
You can have differently-quoted sections within a single "word" (or string, or whatever you want to call it). So, for example, ''hello'' will be parsed as a zero-length single-quoted section, the unquoted section hello, then another zero-length single-quoted section. Since there's no whitespace between them, they're all treated as part of the same word (and since the single-quoted sections are zero-length, they have no effect at all on the resulting word/string).
Double-quotes are slightly different, in that some characters within them retain their special meanings. For example, $ can introduce variable or command substitution, etc (although the result won't be subject to word-splitting like it would be without the double-quotes). Backslashes also function as escapes inside double-quotes, so \$ will be treated as a literal dollar-sign, not as the start of a variable expansion or anything. Other characters that can have their special meaning removed by backslash-escaping are backslashes themselves, and... double-quotes! You can include a double-quote in a double-quote by escaping it. The double-quoted section ends a the next non-escaped double-quote.
So compare:
echo ""hello"" # just prints hello
echo "\"hello\"" # prints "hello", because the escaped
# quotes are part of the string
echo "$PATH" # prints the value of the PATH variable
echo "\$PATH" # prints $PATH
echo ""'$PATH'"" # prints $PATH, because it's in
# single-quotes (with zero-lenght
# double-quoted sections on each side
Also, single- and double-quotes have no special meaning within the other type of quote. So:
echo "'hello'" # prints 'hello', because the single-quotes
# are just ordinary characters in a
# double-quoted string
echo '"hello"' # similarly, prints "hello"
echo "'$PATH'" # prints the PATH variable with
# single-quotes around it (because
# $variable expands in double-quotes)
To give context, I'm trying to create a simple version of bash, and for that I need to mimic the way bash parses content with multiple sets of single and double quotes. I can't figure out the overall procedure by which bash handles quotes inside quotes. I noticed some repeated patterns but still don't have the full picture.
For instance this example:
$ "'"ls"'"
evaluates to:
$ 'ls'
or even this uglier example:
$ "'"'"""'"ls"'"""'"'"
evaluates to:
$ '"""ls"""'
I noticed the following patterns arise:
if count of wrapping quotes are even it evaluates to what's inside the inverse quotes exclusively
if count of wrapping quotes are odd it evaluates to what's inside the inverse quotes inclusively.
For example even wrapping quotes:
$ ""'ls'""
evaluates to what's inside the inverse quotes (single quotes) without the single quotes themselves, evaluation:
$ ls
Or for odd count of wrapper quotes:
$ '''"ls"'''
it evaluates to content of double quotes inclusively:
$ "ls" : command not found.
Still I don't get the full picture of how this parsing pattern for more complex quotes inside quotes is done.
Quotes are processed sequentially, looking for matching closing quotes. Everything between the starting and ending quote becomes a single string. Nested quotes have no special meaning.
"'"ls"'"
When it processes the first ", it scans looking for the next " that ends the string, which contains '.
Then it scans the fixed string ls.
When it processes the " after ls, it scans looking for the next ", resulting in another string '.
These are all concatenated, resulting in 'ls'.
"'"'"""'"ls"'"""'"'"
"'" is the string '.
'"""' is the string """
"ls" is the string ls
'"""' is the string """
"'" is the string '.
Concatenating them all together produces '"""ls"""'
""'ls'""
"" is an empty string. 'ls' is the string ls. "" is another empty string. Concatenating them together produces ls.
'''"ls"'''
'' is an empty string. '"ls"' is the string "ls" (containing literal double quotes). '' is an empty string. Concatenating them produces "ls". Since there's no command with that name (including the literal double quotes), you get an error.
There are differences between single and double quotes, but they don't affect any of the examples you posted. See Difference between single and double quotes in Bash
In a shell script I would like to quote this string of special characters \'%"\"'\ How do I escape the quotes/backslashes inside the string ?
If you use single quotes around the whole string, then the only thing you need to worry about is replacing every ' with '"'"':
$ string='\'"'"'%"\"'"'"'\'
$ echo "$string"
\'%"\"'\
This means:
' close the previous single-quoted string
"'" a new double-quoted string, containing a single quote
' open a new single-quoted string
The shell concatenates adjacent strings, so you get a single quote where you want it. You can replace the middle part by \' but personally I think that's more confusing!
How do I escape characters in linux using the sed command?
I want to print something like this
echo hey$ya
But I'm just receiving a
hey
how can escape the $ character?
The reason you are only seing "hey" echoed is that because of the $, the shell tries to expand a variable called ya. Since no such variable exists, it expands to an empty string (basically it disappears).
You can use single quotes, they prevent variable expansion :
echo 'hey$ya'
You can also escape the character :
echo hey\$ya
Strings can also be enclosed in double quotes (e.g. echo "hey$ya"), but these do not prevent expansion, all they do is keep the whole expression as a single string instead of allowing word splitting to separate words in separate arguments for the command being executed. Using double quotes would not work in your case.
\ is the escape character. So your example would be:
~ » echo hey\$ya
hey$ya
~ »
How to match a single quote in sed if the expression is enclosed in single quotes:
sed -e '...'
For example need to match this text:
'foo'
You can either use:
"texta'textb" (APOSTROPHE inside QUOTATION MARKs)
or
'texta'\''textb' (APOSTROPHE text APOSTROPHE, then REVERSE SOLIDUS, APOSTROPHE, then APOSTROPHE more text APOSTROPHE)
I used unicode character names. REVERSE SOLIDUS is more commonly known as backslash.
In the latter case, you close your apostrophe, then shell-quote your apostrophe with a backslash, then open another apostrophe for the rest of the text.
As noted in the comments to the question, it's not really about sed, but how to include a quote in a quoted string in a shell (e.g. bash).
To clarify a previous answer, you need to escape the quote with a backslash, but you can't do that within a single-quoted expression. From the bash man page:
Enclosing characters in single quotes
preserves the literal value of each
character within the quotes. A single
quote may not occur between single
quotes, even when preceded by a
backslash.
Therefore, you need to terminate the quoted expression, insert the escaped quote, and start a new quoted expression. The shell's quote removal does not add any extra spaces, so in effect you get string concatenation.
So, to answer the original question of how to single quote the expression 'foo', you would do something like this:
sed -e '...'\''foo'\''...'
(where '...' is the rest of the sed expression).
Overall, for the sake of readability, you'd be much better off changing the surrounding quotes to double quotes if at all possible:
sed -e "...'foo'..."
[As an example of the potential maintenance nightmare of the first (single quote) approach, note how StackOverflow's syntax highlighting colours the quotes, backslashes and other text -- it's definitely not correct.]
For sed, a very simple solution is to change the single quotation format to a double quote.
For a given variable that contains single quotes
var="I'm a string with a single quote"
If double quotes are used for sed, this will match the single quote.
echo $var | sed "s/'//g"
Im a string with a single quote
Rather than single quotes, which will hang
echo $var | sed 's/'//g'
You can also use ['] to match a literal single quote without needing to do any shell quoting tricks.
myvar="stupid computers can't reason about life"
echo "$myvar" | sed -e "s/[']t//"
Outputs:
stupid computers can reason about life