Backslash usage in different commands

7,475

Solution 1

Backslash is often used to say “make the next character stand for itself instead of giving it a special meaning”. We say that backslash quotes the next character. This meaning is present in many programming languages, including shell syntax. For example, in rpm-qa rpmname\*, the backslash causes the * character to be passed in the argument to the rpm-qa command. In contrast, rpm-qa rpmname* would replace rpmname* by the list of file names in the current directory starting with rpmname. (If there is no matching file then bash leaves rpmname* alone; zsh would by default complain that there are no matches.)

The shell offers another way to interpret a character literally, i.e. to make it stand for itself rather than be interpreted in some special way. That's quoting, which cancels the special meaning of a whole sequence of characters. There are two kinds of quotes: single quotes ' make every character stand for itself until the next single quote, whereas double quotes " conserve a special meaning for a few characters (", $, \ and `). In echo 'that'\''s no moon', the echo command receives a single argument, which is the concatenation of that (written with a literal string, not that there was any character with a special meaning in that particular case), ' (backslash-single quote cancels the special meaning of that single quote, so this expands to one single quote character), and s no moon (the spaces lose their special meaning since they're within quotes: instead of separating arguments, they're part of the argument).

In the shell, when backslash has a special meaning, that's usually to quote the next character. But:

  • Inside single quotes, backslash has no special meaning.
  • Inside double quotes, backslash only quotes the next character if it's one of "$\`. Otherwise both the backslash and the following character are interpreted literally, e.g. "\a" is the two-character string \a.
  • Inside dollar-single-quote literals, backslash has a different meaning similar to the one in C. A backslash followed by octal digits or by certain letters provides alternate ways of entering characters, which is useful for unprintable characters. For example, \n is a lowercase N, "\n" is backslash+n, but $'\n' is a newline character.

In grep '\s/tmp' /etc/fstab, the single quotes cause grep to receive the argument \s/tmp. This argument is a regular expression. There are many syntax variants for regular expressions, but most based on one of two standards: POSIX basic regular expressions (BRE) and extended regular expressions (ERE). ERE follow the widespread convention that backslash followed by anything other than a letter or digit quotes the following character. But for historical reasons, in BRE, a backslash can sometimes make the next character special when it wouldn't otherwise be. In this case, \s is a GNU grep extension to the basic regex syntax, available both with BRE and with ERE, meaning one whitespace character. Thus grep '\s/tmp' /etc/fstab lists lines in /etc/fstab that contain /tmp preceded by a space or tab.

Solution 2

The \ is used for both escaping special characters, and for triggering regular expressions.

Your rpm command is escaping *, which, in this case, is functionally the same as not escaping it. RPM knows that * is an invalid package character, so it interprets it even if you escape it. Escaping a special character is more often used in situations like handling file names with non-alphanumeric.

Assuming two files, one named 'foo-biz-bar' and the other 'foo*bar', and we only want to see 'foo*bar'. The first result below occurs because an unescaped * is a blob wildcard.

$ ls foo*bar
foo*bar foo-biz-bar
$ ls foo\*bar
foo*baz

The \s in the grep example is a regular expression meaning 'any whitespace', meaning tabs and spaces.

Further Reading

Exhaustive lists of regular expressions are hard to come by on line, but you can start here.

A book that helped me significantly was 'Unix Shells by Example'. Extensive sed, grep, and awk usage were all covered as well.

Solution 3

I'm assuming that you are using bash or something like that.

First of all you have to understand how bash is evaluating your input. There are lots of special characters that you can use in bash. A few of them are for example * ; ~ $

When you enter your input, bash will try to replace all characters that should be. For example variables that begin with a $ sign. The * will be replaced with every file/directory that is present in the directory you are currently in (Determine it with pwd).

If the replacing step is done, bash will finally execute (with a fork()) the program that you have specified.

The \ tells the bash to ignore the given special character: \*

Solution 4

You are right, there's a common convention that the backslash is used for escaping characters, either said character has a special meaning and you want it to be literal:

# echo 'It\'s a string!'

In the above example the apostrophe is used to delimit a literal string, but since you need an apostrophe inside the string you must escape it.

The other case is the opposite, when you need a "normal" character to have some special meaning:

# grep '\s/tmp' /etc/fstab

In the above example the backslash is to tell grep that the s has special meaning and is not a literal s (is a RegEx blank space: space, tab, newline, carriage return, vertical tab)

In other words, when a character has 2 possible meanings you escape it for it to be the secondary meaning.

Edit:

For your first example:

rpm-qa rpmname\*

Here * has a special meaning (anything that starts with 'rpmname') but to avoid the shell trying to expand it you escape it so the command rpm gets the literal * and can process it accordingly.

This goes down for as many times the strings will be interpreted and can be a real struggle when the string is passed around by several commands.

Share:
7,475

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin over 1 year

    I have been trying to get a better understanding of how backslash is used in certain commands. I understand its usage for escaping special characters (Such as echo 'that'\''s no moon' ), but the output from other commands are a bit confusing. For example:

    rpm-qa rpmname\*
    

    grep '\s/tmp' /etc/fstab

    Could someone please break these down for me? Also curious about any other usages you may know of. Thank you!

  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 7 years
    Your first example is wrong. In the shell, a backslash is not special inside a single-quoted string. The shell will complain that the third ' is unmatched.
  • Dalvenjia
    Dalvenjia about 7 years
    @Gilles: Opening and closing string blocks is the "special" meaning of the apostrophe, or better known as single quote, whenever a single one is used without escaping it will throw an error because it expects the closing one.