Why does "\\\\" equals "\\" in zsh? - bash

So to write a backslash to stdout you do
zsh$ echo \\
\
You would think that to output 2 backslashes, you need to run this:
zsh$ echo \\\\
\
Wrong, You need 6 or 8:
zsh$ echo \\\\\\
\\
zsh$ echo \\\\\\\\
\\
Why on earth would I need 8 backslashes ?
Behaviors in different shells :
ksh$ echo \\\\
\\
zsh$ echo \\\\
\
bash$ echo \\\\
\\
sh$ echo \\\\
\
csh$ echo \\\\
\\

You are probably used to bash's built-in echo, which does not perform expansion of escape sequences. POSIX echo, however, does. zsh follows the POSIX specification, so when you write echo \\\\\\, here's what happens.
Quote removal reduces \\\\\\ to \\\; each escaped \ becomes a literal \.
echo takes the three \ it receives, and replaces the first \\ with \. The remaining \ doesn't precede anything, so it is treated literally.
The final result is an output of two \.
With echo \\\\\\\\, here's what happens.
As before, \\\\\\\\ becomes \\\\, because each pair of backslashes becomes a single \ after quote removal.
echo takes the 4 backslashes, and replaces the first \\ with \ and the second \\ with \ as well, since this time it received two matched pairs.
The final result is again two \.
bash probably inherited its non-POSIX comformance from ksh, sh is by definition a POSIX-comformant shell, and it's best not to think about what csh is doing.

Not only zsh, it's default behavior in terminal, backslash (\) is a special character used to tell bash script that you want to other params/texts in newline, so to avoid newline,u need add another backslash to escape special character, since backslash also used for escape special character

Related

running ffmpeg.exe from inside bash file [duplicate]

I am running these two commands in Git bash.
Why they behave differently? Aren't they supposed to do the same thing or am I missing something?
git diff > D:\Patches\afterWGComment.txt
creates file PatchesafterWGComment.txt in D:/
git diff > D:/Patches/afterWGComment.txt
correctly creates file afterWGComment.txt in D:/Patches/
Note that D:/Patches/ folder is present before running the above commands.
Bash treats backslash as an escape character, meaning that the symbol following it is interpreted literally, and the backslash itself is dropped.
$ echo $HOME
/home/user
$ echo \$HOME
$HOME
Under Windows, where backslash serves as a path separator, this causes some inconvenience. Fortunately, inside single quotes a backslash character loses its special meaning and is treated literally (as any other character, except a single quote):
$ echo '\$HOME'
\$HOME
Therefore, if you are going to copy&paste a Windows path into Git bash, put it inside single quotes:
git diff > 'D:\Patches\afterWGComment.txt'
Backslash is an escape character used to escape meta characters. This means you need to escape the escape:
D:\\Patches\\afterWGComment.txt
Alternative you can put your string in single quotes, which will make all characters literal:
'D\Patches\afterWGComment.txt'
Some meta characters: *, ~, $, !, ...
Well the Backslash (\) in Linux generally means a escape character. So in your case the backslash is escaping strings. Try with a cd "D:\Patches\afterWGComment.txt" and you can see the difference.
The back slash has a very long history in Unix (and therefore in Linux) of meanning: quote next character.
There are three ways to quote in the shell (where you type commands):
The backquote (\)
Single quotes (')
Double quotes (")
In the order from stronger to softer. For example, a $ is an special character in the shell, this will print the value of a variable:
$ a=Hello
$ echo $a
Hello
But this will not:
$ echo \$a
$a
$ echo '$a'
$a
$ echo "$a"
Hello
In most cases, a backslash will make the next character "not special", and usually will convert to the same character:
$ echo \a
a
Windows decided to use \ to mean as the same as the character / means in Unix file paths.
To write a path in any Unix like shell with backslashes, you need to quote them:
$ echo \\
\
$ echo '\'
\
$ echo "\\"
\
For the example you present, just quote the path:
$ echo "Hello" > D:\\Patches\\afterWGComment.txt
That will create the file afterWGComment.txt that contains the word Hello.
Or:
$ echo "Hello" > 'D:\Patches\afterWGComment.txt'
$ echo "Hello" > "D:\\Patches\\afterWGComment.txt"
$ echo "Hello" > "D:/Patches/afterWGComment.txt"
Quoting is not simple, it has adquired a long list of details since the 1660's.

Backticks having different output from $() [duplicate]

This question already has answers here:
What is the difference between $(command) and `command` in shell programming?
(6 answers)
Closed 7 years ago.
Can anyone explain the differences between `` (back-quotes) and $() in Linux?
Thank you very much!
By now , I just found that :
$echo `echo \\\\ `
\
$echo $(echo \\\\ )
\\
It's documented in man bash:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or
\. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all
characters between the parentheses make up the command; none are treated specially.
The more important difference is how they nest:
echo $(echo $(echo a))
echo `echo `echo a`` # Wrong
echo `echo \`echo a\``
Back-quotes(``) and $() can be both used for command-substitution, but they have minor difference.
Take the cases mentioned in the question as examples:
$echo `echo \\\\ `
The 1st and 3rd "\" will be treated as escapes, echo \\\\ will be evaluated as "\\"
Therefore, the above command is equal as:
$echo \\
And the first backslash is treated as escape, so the output is:
\
In the case of $(), there is a little tricky, what is evaluated inside $() will be passed as an argument to the outside command.
As an example:
$echo $(echo \\\\ )
What is inside the $() is evaluated as "\\", which is the same as the previous case. What's different is that "\\" will be passed directly to the outside echo command, the first backslash will not be treated as an escape.
Therefore we will got the output:
\\

Tripple backslash in Bash 'echo -e' is acting strange

I have multiple Bash variables for ANSI terminal colors. One is ANSI_NOCOLOR and defined as this:
ANSI_NOCOLOR="\e[0m"
When I use it togather with a backslash character \ (escaped as \\ in Bash strings), I get an unexpected output.
Example:
echo -e "command --with --many --options \\$ANSI_NOCOLOR"
echo -e "--more --options"
This results in:
command --with --many --options \e[0m
--more --options
This example can be reduced to:
$ echo -e "\\\e[0m"
\e[0m
Why is a tripple backslash in Bash not acting as normally known from other C-like languages?
Expected / C-like behavior:
Escape sequences are left-associative. Thus,
the first two \\ are printed as \,
the remaining \ is doing a look-ahead(1) to find e for creating the ESC character.
Workaround:
After some planing with backslashes, I found, that 5 !! backslashes are required. I still would like to read an explanation, why it behaves as it is.
$ echo -e "\\\\\e[33mfoo\e[0m"
\foo
It's hard to control a color-reset sequence, so my workaround uses two ANSI color escape sequences, to set it to yellow and back to default.
This happens because there are two levels of escaping at work:
escaping for the double quoted string. This pass recognizes \\ but not \e
echo -e escape sequences. This pass recognizes both \\ and \e.
So:
The initial string is \\\e
The double quotes replace the \\ but leaves the unsupported \e alone
You now have \\e
Echo replaces the \\
You now have \e
This is one of the many reasons why you should prefer printf over echo whenever any value may contain a backslash.

sh-3.2 double vs quadruple backslash

I'm on OS X 10.11.5, and I have a /bin/bash on my system with version 3.2.57. The /bin/sh reports the same thing, suggesting that /bin/sh is really bash 3.2.
My /bin/sh exhibits some weird behaviour: echo \\ gives a single backslash (as expected), but echo \\\\ also gives \ as output, and you need 6 backslashes to get two as output. Demonstration:
>> /bin/bash
~$ echo \\
\
~$ echo \\\\
\\
~$ echo \\\\\\
\\\
~$ exit
>> /bin/bash --posix
~$ echo \\
\
~$ echo \\\\
\\
~$ echo \\\\\\
\\\
~$ exit
>> /bin/sh
sh-3.2$ echo \\
\
sh-3.2$ echo \\\\
\
sh-3.2$ echo \\\\\\
\\
sh-3.2$ exit
>> /bin/sh --posix
sh-3.2$ echo \\
\
sh-3.2$ echo \\\\
\
sh-3.2$ echo \\\\\\
\\
sh-3.2$ exit
>> /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
>> /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
Question: why doesn't echo \\\\ give two backslashes as output in /bin/sh, while it does in /bin/bash?
More info:
sh-3.2$ echo \\
\
sh-3.2$ echo \\\\
\
sh-3.2$ echo \\\\\\
\\
sh-3.2$ echo \\\\\\\\
\\
sh-3.2$ echo \\\\\\\\\\
\\\
sh-3.2$ echo \\\\\\\\\\\\
\\\
You are seeing the difference between the POSIX and bash implementations of echo. In short, POSIX echo expands certain escaped characters, while bash does not treat a backslash specially unless you use the -e option. Also, bash uses the POSIX implementation when it runs as sh, or when you explicitly set the xpg_echo option to use the POSIX version.
# POSIX
$ echo 'a\nb'
a
b
# bash
$ echo 'a\nb'
a\nb
$ echo -e 'a\nb'
a
b
Single quotes are just a shorthand for escaping every character contained with in. Using explicit escaping instead of single quotes for all of the above:
# POSIX
$ echo \a\\\n\b
a
b
# bash
$ echo \a\\\n\b
a\nb
$ echo -e \a\\\n\b
a
b
Double quotes are similar to single quotes, except the shell first processes a very limited set of escaped characters first. This is because $ is treated specially inside double quotes, indicating a parameter expansion. You can escape the $ to prevent this, and you can escape a backslash to prevent it from escaping the following character. In all other cases, the backslash is treated literally and passed along to echo.
$ foo=5
$ echo "$foo"
5
$ echo "\$foo"
$foo
$ echo "\\$foo"
\5
$ echo "\\\$foo"
\$foo
$ echo "\t"
\t
With that out of the way, how does each shell create echo \\\\? First, both shells perform quote removal to eliminate quotations marks and escaping backslashes. The first backslash escapes the second, and the third escapes the fourth, leaving just a pair of literal backslashes as the argument to echo. The POSIX version of echo treats \\ as a literal backslash, while the bash version treats \\ as a pair of literal backslashes.

bash: assign punctuation to variable

when I assign like this:
rmall="\,\.\?\!\:\;\(\)\[\]\{\}\"\'"
then echo $rmall, I got this:
\,\.\?\!\:\;\(\)\[\]\{\}\"\'
But what I want is only , How can I do?
,.?!:;()[]{}"'
as later I need to remove those.
Thank you
You are double quoting by using quotes and backslashes. Use one or the other.
Note: You will always need to use backslash for escaping your quote character but otherwise not needed.
Inside double quotes, only three escape sequences are treated specially:
\" is replaced by a literal "
\$ is replaced by a literal $
\\ is replaced by a literal \
These three are required to allow the literal character in contexts where they would normally produce special behavior. \", obviously, lets you include a double-quote inside a double-quoted string. \$ lets you output a literal dollar sign where it would otherwise trigger parameter substitution:
bash $ foo=5; echo "\$foo = $foo"
$foo = 5
\\ lets you output a literal backslash that precedes a parameter substitution or at the end of a string.
bash $ foo=5; echo "\\$foo"
\5
bash $ echo "Use a \\"
Use a \
A backslash followed by any other character is treated literally:
bash $ echo "\x"
\x

Resources