How to quote string of special characters? - 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!

Related

Escape special characters in BASH [duplicate]

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 are strings with multiple kinds of quotes interpreted in bash?

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

How to escape characters from a single command?

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
~ »

I try to replace the backward slash with forward slash using gsub but it's not working

puts "C:\WATIR\gopal\**".gsub("\\", "/")
It's giving me the output
C:WATIRgopal**
Can anyone suggest me where do I go wrong?
The problem is not with the #gsub, but with the string construction itself:
"C:\WATIR\gopal\**" # => "C:WATIRgopal**"
\ is used for escaping character. \W for example will try go escape the W character, instead of make two characters - \ and W. One way to fix it is to escape the escaping with another \:
"C:\\WATIR\\gopal\\**" # => "C:\\WATIR\\gopal\\**"
The better way is to use single quotes, where \ has no special meaning:
'C:\WATIR\gopal\**' # => "C:\\WATIR\\gopal\\**"
Additionally, prefer #tr over #gsub when you want to replace a single character with another:
'C:\WATIR\gopal\**'.tr('\\', '/') # => "C:/WATIR/gopal/**"
In your question,.
puts "C:\WATIR\gopal\**".gsub("\\", "/")
gives
C:WATIRgopal**
because it is treating \ as an escape character and leaving it.
Single Quotes:
'C:\WATIR\gopal\**'.gsub("\\", "\/")
use single quote to prevent escaping '\'
Double quotes:
If you want to use only doublequote:
puts "C:\\WATIR\\gopal\\**".gsub("\\", "\/")
This gives o/p:
C:/WATIR/gopal/**
Is this because the '\ ' is interpreted as a special character in the double quote string but in the single quoted string the characters are preserved as is
Difference between single and double quotes:
Ruby only interprets escape sequences in double quoted strings.
In a single quoted string, only \ (backslash backslash) and \' (backslash quote) are taken as special characters.
You should use double quoted strings only when you need more interpretation.
Otherwise, single quotes provide a performance boost.

How to match a single quote in sed

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

Resources