1.bash-轉義&引號


引號和轉義

Bash 只有一種數據類型,就是字符串。不管用戶輸入什么數據,Bash 都視為字符串。因此,字符串相關的引號和轉義,對 Bash 來說就非常重要。

轉義

某些字符在 Bash 里面有特殊含義(比如$&*)。

$ echo $date

$

上面例子中,輸出$date不會有任何結果,因為$是一個特殊字符。

如果想要原樣輸出這些特殊字符,就必須在它們前面加上反斜杠,使其變成普通字符。這就叫做“轉義”(escape)。

$ echo \$date
$date

上面命令中,只有在特殊字符$前面加反斜杠,才能原樣輸出。

反斜杠本身也是特殊字符,如果想要原樣輸出反斜杠,就需要對它自身轉義,連續使用兩個反斜線(\\)。

$ echo \\
\

上面例子輸出了反斜杠本身。

反斜杠除了用於轉義,還可以表示一些不可打印的字符。

  • \a:響鈴
  • \b:退格
  • \n:換行
  • \r:回車
  • \t:制表符

如果想要在命令行使用這些不可打印的字符,可以把它們放在引號里面,然后使用echo命令的-e參數。

$ echo a\tb
atb

$ echo -e "a\tb"
a        b

上面例子中,命令行直接輸出不可打印字符\t,Bash 不能正確解釋。必須把它們放在引號之中,然后使用echo命令的-e參數。

換行符是一個特殊字符,表示命令的結束,Bash 收到這個字符以后,就會對輸入的命令進行解釋執行。換行符前面加上反斜杠轉義,就使得換行符變成一個普通字符,Bash 會將其當作空格處理,從而可以將一行命令寫成多行。

$ mv \
/path/to/foo \
/path/to/bar

# 等同於
$ mv /path/to/foo /path/to/bar

上面例子中,如果一條命令過長,就可以在行尾使用反斜杠,將其改寫成多行。這是常見的多行命令的寫法。

單引號

Bash 允許字符串放在單引號或雙引號之中,加以引用。

單引號用於保留字符的字面含義,各種特殊字符在單引號里面,都會變為普通字符,比如星號(*)、美元符號($)、反斜杠(\)等。

$ echo '*'
*

$ echo '$USER'
$USER

$ echo '$((2+2))'
$((2+2))

$ echo '$(echo foo)'
$(echo foo)

上面命令中,單引號使得 Bash 擴展、變量引用、算術運算和子命令,都失效了。如果不使用單引號,它們都會被 Bash 自動擴展。

由於反斜杠在單引號里面變成了普通字符,所以如果單引號之中,還要使用單引號,不能使用轉義,需要在外層的單引號前面加上一個美元符號($),然后再對里層的單引號轉義。

# 不正確
$ echo it's

# 不正確
$ echo 'it\'s'

# 正確
$ echo $'it\'s'

不過,更合理的方法是改在雙引號之中使用單引號。

$ echo "it's"
it's

雙引號

雙引號比單引號寬松,大部分特殊字符在雙引號里面,都會失去特殊含義,變成普通字符。

$ echo "*"*

上面例子中,通配符*是一個特殊字符,放在雙引號之中,就變成了普通字符,會原樣輸出。這一點需要特別留意,這意味着,雙引號里面不會進行文件名擴展。

但是,三個特殊字符除外:美元符號($)、反引號(`)和反斜杠(\)。這三個字符在雙引號之中,依然有特殊含義,會被 Bash 自動擴展。

$ echo "$SHELL"/bin/bash$ echo "`date`"Mon Jan 27 13:33:18 CST 2020

上面例子中,美元符號($)和反引號(`)在雙引號中,都保持特殊含義。美元符號用來引用變量,反引號則是執行子命令。

$ echo "I'd say: \"hello!\""I'd say: "hello!"$ echo "\\"\

上面例子中,反斜杠在雙引號之中保持特殊含義,用來轉義。所以,可以使用反斜杠,在雙引號之中插入雙引號,或者插入反斜杠本身。

換行符在雙引號之中,會失去特殊含義,Bash 不再將其解釋為命令的結束,只是作為普通的換行符。所以可以利用雙引號,在命令行輸入多行文本。

$ echo "helloworld"helloworld

上面命令中,Bash 正常情況下會將換行符解釋為命令結束,但是換行符在雙引號之中就失去了這種特殊作用,只用來換行,所以可以輸入多行。echo命令會將換行符原樣輸出,顯示的時候正常解釋為換行。

雙引號的另一個常見的使用場合是,文件名包含空格。這時就必須使用雙引號(或單引號),將文件名放在里面。

$ ls "two words.txt"

上面命令中,two words.txt是一個包含空格的文件名,否則就會被 Bash 當作兩個文件。

雙引號會原樣保存多余的空格。

$ echo "this is a     test"this is a     test

雙引號還有一個作用,就是保存原始命令的輸出格式。

# 單行輸出$ echo $(cal)一月 2020 日 一 二 三 四 五 六 1 2 3 ... 31# 原始格式輸出$ echo "$(cal)"      一月 2020日 一 二 三 四 五 六          1  2  3  4 5  6  7  8  9 10 1112 13 14 15 16 17 1819 20 21 22 23 24 2526 27 28 29 30 31

上面例子中,如果$(cal)不放在雙引號之中,echo就會將所有結果以單行輸出,丟棄了所有原始的格式。

Here 文檔

Here 文檔(here document)是一種輸入多行字符串的方法,格式如下。

<< tokentexttoken

它的格式分成開始標記(<< token)和結束標記(token)。開始標記是兩個小於號 + Here 文檔的名稱,名稱可以隨意取,后面必須是一個換行符;結束標記是單獨一行頂格寫的 Here 文檔名稱,如果不是頂格,結束標記不起作用。兩者之間就是多行字符串的內容。

下面是一個通過 Here 文檔輸出 HTML 代碼的例子。

$ cat << _EOF_<html><head>    <title>    The title of your page    </title></head><body>    Your page content goes here.</body></html>_EOF_

Here 文檔內部會發生變量替換,同時支持反斜杠轉義,但是不支持通配符擴展,雙引號和單引號也失去語法作用,變成了普通字符。

$ foo='hello world'$ cat << _example_$foo"$foo"'$foo'_example_hello world"hello world"'hello world'

上面例子中,變量$foo發生了替換,但是雙引號和單引號都原樣輸出了,表明它們已經失去了引用的功能。

如果不希望發生變量替換,可以把 Here 文檔的開始標記放在單引號之中。

$ foo='hello world'$ cat << '_example_'$foo"$foo"'$foo'_example_$foo"$foo"'$foo'

上面例子中,Here 文檔的開始標記(_example_)放在單引號之中,導致變量替換失效了。

Here 文檔的本質是重定向,它將字符串重定向輸出給某個命令,相當於包含了echo命令。

$ command << token  stringtoken# 等同於$ echo string | command

上面代碼中,Here 文檔相當於echo命令的重定向。

所以,Here 字符串只適合那些可以接受標准輸入作為參數的命令,對於其他命令無效,比如echo命令就不能用 Here 文檔作為參數。

$ echo << _example_hello_example_

上面例子不會有任何輸出,因為 Here 文檔對於echo命令無效。

此外,Here 文檔也不能作為變量的值,只能用於命令的參數。

Here 字符串

Here 文檔還有一個變體,叫做 Here 字符串(Here string),使用三個小於號(<<<)表示。

<<< string

它的作用是將字符串通過標准輸入,傳遞給命令。

有些命令直接接受給定的參數,與通過標准輸入接受參數,結果是不一樣的。所以才有了這個語法,使得將字符串通過標准輸入傳遞給命令更方便,比如cat命令只接受標准輸入傳入的字符串。

$ cat <<< 'hi there'# 等同於$ echo 'hi there' | cat

上面的第一種語法使用了 Here 字符串,要比第二種語法看上去語義更好,也更簡潔。

$ md5sum <<< 'ddd'# 等同於$ echo 'ddd' | md5sum

上面例子中,md5sum命令只能接受標准輸入作為參數,不能直接將字符串放在命令后面,會被當作文件名,即md5sum ddd里面的ddd會被解釋成文件名。這時就可以用 Here 字符串,將字符串傳給md5sum命令。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM