How to Escape the Bang (!) Character in Linux Bash Shell

bash + Linux + how to ignore the character !

Use set +H before your command to disable ! style history substitution:

set +H
ssh 183.34.4.9 "echo -e '#!/bin/bash\nsleep 1\reboot>'/tmp/file"

# enable hostory expnsion again
set -H

How do I escape an exclamation mark in bash?

Exclamation mark is preserved literally when you include it in a single-quoted string.

Example:

git commit -m 'Frustrating <insert object of frustration here>!'

How to pass argument with exclamation mark on Linux?

You should be able to simply wrap things in single quotes in the shell.

$ emailsender.py -u username -p 'pass!!'

Curl - Exclamation mark in User Auth/Password

 curl -u UserName\\WithSlash:PasswordWithExclamation\!  http://....

works fine.

it sends

 GET / HTTP/1.1
Authorization: Basic VXNlck5hbWVcV2l0aFNsYXNoOlBhc3N3b3JkV2l0aEV4Y2xhbWF0aW9uIQ==
User-Agent: curl/7.21.0
Host: teststuff1.com:80
Accept: */*

which is "UserName\WithSlash:PasswordWithExclamation!" in the auth string.

Escaping characters in bash alias

Best Advice: Don't.

Use a function instead:

th() { tmux new -s "${PWD##*/}" "$@"; }

${PWD##*/} is a parameter expansion which strips everything up to and including the last / from the contents of $PWD.


Alternate Approach: Literal Quotes

The issue in your original code is that it contains syntactic quotes -- ones parsed by the shell to determine where single-quoted parsing rules begin and end -- in places where what you actually want is literal quotes, ones which are treated as data (and thus become part of the alias).

One way to make these quotes literal would be to use the $'' quoting form instead, which lets you use literal backslashes to escape inner quotes, making them literal rather than syntactic:

alias th=$'tmux new -s $(pwd | tr \'\\\/\' \'\\n\' | tail -n 1)'

Note that when using $'', literal backslashes need to be escaped as well (thus, written as \\ rather than \).


Explanation: Why

The quoting of strings in POSIX shell languages is determined on a character-by-character basis. Thus, in the case of:

'$foo'"$((1+1))"baz

...$foo is single-quoted and thus treated as a literal string, $((1+1)) is double-quoted and thus eligible for being treated as arithmetic expansion, and baz is unquoted -- even though all three of these are concatenated to form a single word ($foo2baz).

These quotes are all syntactic -- they're instructions to the shell -- not literal (which would mean they'd be part of the data to which that string evaluates).


How This Applies To Your Previous Command

In

alias th='tmux new -s $(pwd | tr '\/' '\n' | tail -n 1)'  

...the single quotes in the arguments to tr end the single quotes started at the beginning of the alias. Thus, \/ and \n are evaluated in an unquoted context (in which \/ becomes just /, and \n becomes just n) -- and since, as described above, multiple differently-quoted substrings can just be concatenated into a single larger string, you get your prior command, not an alias.

Single quotes around variable value

Like every other command the assignment of a value to a variable will be parsed by the shell, too. To prevent the shell from parsing the special characters must be "quoted". Single characters can be quoted with the backslash (\), multiple characters can be quoted with single quotes (') or double quotes ("). Within single quotes every character will be taken literally. Double-quoted characters will mostly taken literally, with the main exeption (among some others): variables will be replaced with their contents.

To assign the Value "JSBDbshe66!#12$@a" in the command line it must be single-quoted because of the bang (!) sign (see bash bang for further information):

:~$ DEV_ARM_CLIENT_SECRET='JSBDbshe66!#12$@a'

The command

:~$ echo $DEV_ARM_CLIENT_SECRET

gives you the desired output:

JSBDbshe66!#12$@a

To copy this value to another variable just enter in the command line:

ARM_CLIENT_SECRET=$DEV_ARM_CLIENT_SECRET

Alternatively you can enter:

ARM_CLIENT_SECRET="$DEV_ARM_CLIENT_SECRET"

to receive the same result. The variable-name between the double quotes will be replaced with the value and finally the shell removes the Quotes. If you put the variable name between single quotes

ARM_CLIENT_SECRET='$DEV_ARM_CLIENT_SECRET'

every character between the quotes will be taken literally:

:~$ echo $ARM_CLIENT_SECRET

$DEV_ARM_CLIENT_SECRET

If you quote the single quotes via Backslash

:~$ ARM_CLIENT_SECRET=\'$DEV_ARM_CLIENT_SECRET\'

the value of "$ARM_CLIENT_SECRET" will be the same as $DEV_ARM_CLIENT_SECRET with an additional leading and a trailing single quote:

:~$ echo $ARM_CLIENT_SECRET

'JSBDbshe66!#12$@a'



Related Topics



Leave a reply



Submit