13

Many questions like 'How to type the double-quote char (")?' are being asked, and we don't want to clutter our community with the same answer (Type it as \" if not enclosed in 's, " if enclosed in 's.) So, the question is here.

You can't type special chars into a terminal like normal ones, e.g. this command will fail:

echo Updates (11)

So, how to type in these chars in the terminal as if they were normal ones?

!#$^&*?[](){}<>~;'"\|<space><tab><newline>
  • There's no Unix shell that I know where carriage-return is special. =, @ and % are special in some shells in some contexts. – Stéphane Chazelas Jul 15 '16 at 17:11
  • @StéphaneChazelas Umm... carriage return (^M) acts like line feed (^J) to me (Ubuntu 14.04, sh). – EKons Jul 15 '16 at 17:58
  • No, your terminal driver transforms ^M to ^J on input but ^M is not special to the shell and doesn't need quoted. Type echo ^V^M | hd and you'll see the 0d character (and the 0a appended by echo). – Stéphane Chazelas Jul 15 '16 at 18:00
  • @StéphaneChazelas Umm... I don't know what hd is, maybe xxd is better as a hex viewer. – EKons Jul 15 '16 at 18:03
  • Whichever. Use POSIX od -tx1 or sed -n l or vim's xxd if you don't have hd. Some systems also have cat -vte or cat -A – Stéphane Chazelas Jul 15 '16 at 18:04
26

That very much depends on the shell. Check your shell manual for details.

Also note that some characters are only special in some contexts. For instance, in most shells,* and ? are only special in list contexts, in POSIX or csh-like shells, ~ is only special at the beginning of a word or following some characters like :. Same for = in zsh. In some shells, [ is only special when matched (with some restrictions) by a ].

In some shells like bash or yash, special characters like blank token delimiters also vary with the locale.

The quoting operators (to remove the special meaning of those characters) also vary greatly between shells.

Bourne-like shells

A summary for Bourne-like shells (that is the shells that have been known to be called sh on some system or another since the 80s):

Bourne shell

Special characters:

  • "\'&|;()^`<>$, space, newline and tab are special in simple command lines when not quoted.
  • # (except in early version) is special at the beginning of a line or following an unquoted space, tab or &|()^<>;`.
  • { and } are only special in that they are shell keywords (so only words in command position).
  • *?[ are special as globbing operators, so only in list contexts. In the case of [, it's [...] that is the globbing operator, either [ or ] only need to be quoted to remove the special meaning.
  • = is special when in contexts where it's treated as an assignment operator. That is, in a simple command, for all words that do not follow an argument (except after set -k).

Quoting operators

  • \ quotes all special characters except newline (\<newline> is a way to continue a long logical line onto the next physical line, so that sequence is removed). Note that backticks add extra complexity as within them, \ is used first to escape the closing backtick and help the parser. Inside double quotes, \ may only be used to escape itself, ", $ and ` (\<newline> is still a line-continuation). Inside a here-document, same except for ". \ is the only way to escape characters inside here documents.
  • "..." double-quotes escape all characters but itself, \, $ and `.
  • '...' single quotes escape all characters but itself.

POSIX shells

POSIX shells behave mostly like the Bourne shell, except that:

ksh

like POSIX except that:

  • {string} is special if string contains an unquoted , (or .. in some cases and with some versions).
  • ksh93 has an additional special quoting operator: $'...' with complex rules. That operator is also found (with some variations) in bash, zsh, mksh and FreeBSD and busybox sh.
  • ksh93 also has a $"..." quoting operator that works like "..." except that the string is subject to localisation (could be configured so it translates to the language of the user). mksh ignores the $ in $"...".

bash

like ksh93 but:

  • in single-byte character locales, all blank (according to the locale) characters are considered as delimiters (like space or tab). In effect, that means you should quote all bytes with the 8th bit set in case they may be a blank character in some locale.
  • When csh history expansion is enabled like in interactive instances, ! is special in some contexts and double quotes do not always escape it. And ^ is special at the beginning of a command.

zsh

like ksh93 but:

  • same note as for bash for csh history expansion
  • = is special as the first character of a word (=ls expands to /bin/ls).
  • { and } can also open and close command groups when not delimited (as in {echo text} works like Bourne's { echo text;}).
  • except for [ alone, [ needs quoted even if not closed with a ].
  • With the extendedglob option enabled, #, ^ and ~ are globbing operators.
  • With the braceccl option, {non-empty-string} is special.
  • $"..." is not supported.
  • as a special quirk, ? is not special when following a % (even quoted or expanded) at the start of a word (to allow the %?name job specification)
  • a rcquotes option (not enabled by default) allows one to enter single quotes as '' inside single quotes à la rc (see below).

yash

like POSIX except that.

  • all blank characters are considered as delimiters.
  • With the brace-expand option, implements zsh-style brace expansion.

For all shells, there are some special contexts where quoting works differently. We've already mentioned here documents and backticks, but there's also [[...]] in ksh and a few other shells, POSIX $((...)), case constructs...

Also note that quoting can have other side-effects when it comes to expansions (with double-quotes), or when applied to here document delimiters. It also disables reserved words and affects alias expansion.

Summary

In Bourne-like shells, !#$^&*?[(){}<>~;'"`\|=, SPC, TAB, NEWLINE and some bytes with the 8th bit set are or may be special (at least in some contexts).

To remove the special meaning so they be treated literally, you use quoting.

Use:

  • '...' to remove the special meaning of every character:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
    
  • \ to remove the special meaning of one character only:

    printf '<%s>\n' foo bar\ baz #comment
    

    Above, only the space character preceded by a \ is passed literally to printf. The other ones are treated by the shell as token delimiters.

  • use "..." to quote characters while still allowing parameter expansion ($var, $#, ${foo#bar}...), arithmetic expansion ($((1+1)), also $[1+1] in some shells) and command substitution ($(...) or the old form `...`. Actually, most of the time, you do want to put those expansions inside double quotes in any case. You can use \ within "..." to remove the special meaning of the characters that are still special (but only them).
  • if the string contains ' character, you can still use '...' for the rest and use other quoting mechanisms that can quote ' like "'" or \' or (where available) $'\'':

    echo 'This is "tricky", isn'\''t it?'
    
  • Use the modern $(...) form of command substitution. Only use the old `...` for compatibility with the Bourne shell, that is to very old system, and only in variable assignments, as in don't use:

    echo "`echo "foo bar"`"
    

    Which won't work with the Bourne shell or AT&T versions of ksh. Or:

    echo "`echo \"foo bar\"`"
    

    Which will work with Bourne and AT&T ksh, but not with yash, but use:

    var=`echo "foo bar"`; echo "$var"
    

    which will work with all.

    Nesting them portably with double quotes is also impossible, so again, use variables. Also beware of the special backslash processing:

    var=`printf '%s\n' '\\'`
    

    Will store only one backslash inside $var, because there's an extra level of backslash processing (for \, `, and $ (and also " when quoted except in yash)) within backticks so you need either

    var=`printf '%s\n' '\\\\'`
    

    or

    var=`printf '%s\n' '\\\'
    

    instead.

Csh family

csh and tcsh have a significantly different syntax, though there is still a lot in common with the Bourne shell as they share a common heritage.

Special characters:

  • "\'&|;()^`<>$, space, newline and tab are special everywhere when not quoted.
  • # (csh is the shell that introduced # as the comment leader) is special at the beginning of a script or following an unquoted space, tab or newline.
  • *?[ are special as globbing operators so in list contexts
  • {non-empty-string} is special (csh is the shell that introduced brace expansion).
  • ! and ^ are special as part of history expansion (again, a csh invention), and quoting rules are special.
  • ~ (tilde expansion also a csh invention) is special in some contexts.

Quoting operators

They are the same as for the Bourne shell, but the behaviour differs. tcsh behaves like csh from the syntax point of view, you'll find that many versions of csh have nasty bugs. Get the latest version of tcsh to get a roughly working version of csh.

  • \ escapes a single character except newline (same as for the Bourne shell). It's the only quoting operator that can escape !. \<newline> doesn't escape it but transforms it from a command separator to a token separator (like space)
  • "..." escapes all characters except itself, $, `, newline and !. Contrary to the Bourne shell, you can't use \ to escape $ and ` inside "...", but you can use \ to escape ! or newline (but not itself except when before a ! or newline). A literal ! is "\!" and a literal \! is "\\!".
  • '...' escapes all characters except itself, ! and newline. Like for double quotes, ! and newline can be escaped with backslash.
  • command substitution is only via the `...` syntax and can hardly be used reliably.
  • variable substitution is also pretty badly designed and error prone. A $var:q operator helps to write more reliable code involving variables.

Summary

Stay away from csh if you can. If you can't use:

  • single quotes to quote most characters. ! and newline still need a \.
  • \ can escape most characters
  • "..." can allow some expansions within it, but that's pretty buggy if they embed newline and/or backslash characters, best may be to use single quotes only and $var:q for variable expansion. You'll need to use loops if you want to join elements of an array reliably.

rc family

rc is the plan9 shell and like its descendants es and akanga has been ported to Unix and unix-likes. That's a shell with a much cleaner and better syntax and the one everyone would be using if we weren't stuck with Bourne-like shells for backward compatibility.

rc/akanga

Special characters

  • #;&|^$=`'{}()<>, SPC, TAB and NEWLINE are always special when not quoted.
  • *?[ are globbing operators.

Quoting operator

'...' is the only quoting operator. A litteral ' is written with '' within single quotes as in:

 echo 'it''s so simple isn''t it?'

es

es could be seen as an experimental shell based on rc.

It has a few differences though. The one of interest for this Q/A is that \ is also a quoting operator (that quotes all special characters except newline) and can also be used to introduce escape sequences like \n for newline, \b for backslash...

fish

fish is a relative newcomer (circa 2005), is primarily intended for interactive use and also has a significantly different syntax from other shells.

special characters

  • "'\()$%{}^<>;&| always special when not quoted (note the % (for pid expansion) as a significant difference from other shells, and ` is not special)
  • # (comment) special when following unquoted space, tab, newline or ;&|^<>
  • *? (but not [...]) globbing operators

Quoting operators

  • \ quotes a single special character except newline, but beware it also doubles as a C escape sequence (\n, \b...) introducer. IOW, \n is not a quoted n but a newline.
  • "..." quotes everything but itself, $ and backslash and backslash can be used to escape those. \<newline> is a line continuation (removed) inside "...".
  • '...' quotes everything but itself and \, and you can use backslash to escape those.
  • I have included only the ones special in all contexts (so that c acts the same as \c, c does not output c: command not found on STDERR, etc.) And I'm talking about sh here. Also, remember that this is a "clean-up" question, i.e. it's here to cover all such characters, so 19+ questions won't have to be asked. The question was posted thanks to an incident that different questions are asked for different such characters, we surely want to clean up here! – EKons Jul 15 '16 at 15:10
  • Well, ?[ are globbing operators, but isn't special in all contexts, but * seems to be, because echo * badly echoes the contents of the current directory (not escaping anything). echo ? echoes a literal ? and echo [ echoes a literal [. Also, ] is a globbing oberator too. – EKons Jul 15 '16 at 15:37
  • 1
    @ΈρικΚωνσταντόπουλος, * as a glob expands to all non-hidden files, ? to non-hidden single-character files, [a-z] to files whose name is a single character between a and z and so on. When they don't match any file (like in your case for ?), depending on the shell, you get a no-match error or the pattern expands to itself. In any case, even on shell where they expand to themselves, they need quoted in case they may match a file. – Stéphane Chazelas Jul 15 '16 at 17:04
  • But, not as a glob, * still expands to something. – EKons Jul 15 '16 at 17:54
  • @ΈρικΚωνσταντόπουλος, * is like ?, if it doesn't match (for the case of * alone, that's when there are only hidden files in the current directory, for a* that's where there's no file whose name starts with a...), it either expands to itself (most Bourne-like shells), or raises a no-match error (csh, tcsh, fish (warning), zsh, bash -O failglob, early Unix shells), (or expands to nothing with the nullglob option of some shells or if there's another pattern that expands to something in csh, tcsh, zsh -o cshnullglob, early unix shells). – Stéphane Chazelas Jul 16 '16 at 6:40
4

1. Escape

Escape all of these characters with a \, like this (does not work on newlines/carriage returns):

$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.

2. Double-quote

Enclose the whole text in "s, like this:

$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!

3. Single-quote

Same as double-quote, but there is no special token.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof
  • 1
    You're describing the behaviour of the the fish shell, not Bourne-like shells where the single quote quotes every character (backslash is not special within '...'). Note that in fish, % is also a special character. – Stéphane Chazelas Jul 15 '16 at 17:08
  • @StéphaneChazelas I don't know how fish works, but my experience is that, in sh, echo '\\' echoes \ and echo '\'' echoes '. – EKons Jul 15 '16 at 17:55
  • 1
    echo '\\' outputs \ because your echo expands ANSI C escape sequences (some echo implementations need echo -e '\\' for that). printf '%s\n' '\\' outputs \\. – Stéphane Chazelas Jul 15 '16 at 18:01
  • Note that sh does not identify a particular shell, there are and have been a lot of different and often incompatible shells called sh. – Stéphane Chazelas Jul 15 '16 at 18:03
  • @StéphaneChazelas Oh okay, I will change that now. By the way, is \' a special token inside a single-quoted character sequence? – EKons Jul 15 '16 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.