Shell Here Document(內嵌檔案/嵌入檔案)

2020-07-16 10:04:45
Shell 還有一種特殊形式的重定向叫做“Here Document”,目前沒有統一的翻譯,你可以將它理解為“嵌入文件”“內嵌文件”“立即文件”。

所謂文件,就是命令需要處理的資料或者字串;所謂嵌入,就是把資料和程式碼放在一起,而不是分開存放(比如將資料放在一個單獨的檔案中)。有時候命令需要處理的資料量很小,將它放在一個單獨的檔案中有點“大動干戈”,不如直接放在程式碼中來得方便。

Here Document 的基本用法為:

command <<END
    document
END

command是 Shell 命令,<<END是開始標誌,END是結束標誌,document是輸入的文件(也就是一行一行的字串)。

這種寫法告訴 Shell 把 document 部分作為命令需要處理的資料,直到遇見終止符END為止(終止符END不會被讀取)。

注意,終止符END必須獨佔一行,並且要定頂格寫。

分界符(終止符)可以是任意的字串,由使用者自己定義,比如 END、MARKER 等。分界符可以出現在正常的資料流中,只要它不是頂格寫的獨立的一行,就不會被作為結束標誌。

【範例1】cat 命令一般是從檔案中讀取內容,並將內容輸出到顯示器上,借助 Here Document,cat 命令可以從鍵盤上讀取內容。
[[email protected] ~]$ cat <<END
> Shell教學
> http://c.biancheng.net/shell/
> 已經進行了三次改版
> END
Shell教學
http://c.biancheng.net/shell/
已經進行了三次改版
<是第二層命令提示字元。

正文中也可以出現結束標誌END,只要它不是獨立的一行,並且不頂格寫,就沒問題。
[[email protected] ~]$ cat <<END
> END可以出現在行首
> 出現在行尾的END
> 出現在中間的END也是允許的
> END
END可以出現在行首
出現在行尾的END
出現在中間的END也是允許的

【範例2】在指令碼檔案中使用 Here Document,並將 document 中的內容轉換為大寫。
#!/bin/bash
#在指令碼檔案中使用立即文件

tr a-z A-Z <<END
one two three
Here Document
END
將程式碼儲存到 test.sh 並執行,結果為:
ONE TWO THREE
HERE DOCUMENT

忽略命令替換

預設情況下,正文中出現的變數和命令也會被求值或執行,Shell 會先將它們替換以後再交給 command,請看下面的例子:
[[email protected] ~]$ name=C語言中文網
[[email protected] ~]$ url=http://c.biancheng.net
[[email protected] ~]$ age=7
[[email protected] ~]$ cat <<END
> ${name}已經${age}歲了,它的網址是 ${url}
> END
C語言中文網已經7歲了,它的網址是 http://c.biancheng.net

你可以將分界符用單引號或者雙引號包圍起來使 Shell 替換失效:
[[email protected] ~]$ name=C語言中文網
[[email protected] ~]$ url=http://c.biancheng.net
[[email protected] ~]$ age=7
[[email protected] ~]$ cat <<'END'  #使用單引號包圍
> ${name}已經${age}歲了,它的網址是 ${url}
> END
${name}已經${age}歲了,它的網址是 ${url}

忽略製表符

預設情況下,行首的製表符也被當做正文的一部分。
#!/bin/bash

cat <<END
    Shell教學
    http://c.biancheng.net/shell/
    已經進行了三次改版
END
將程式碼儲存到 test.sh 並執行,結果如下:
    Shell教學
    http://c.biancheng.net/shell/
    已經進行了三次改版

這裡的製表符僅僅是為了格式對齊,我們並不希望它作為正文的一部分,為了達到這個目的,你可以在<<END之間增加-,請看下面的程式碼:
#!/bin/bash

#增加了減號-
cat <<-END
    Shell教學
    http://c.biancheng.net/shell/
    已經進行了三次改版
END
這次的執行結果為:
Shell教學
http://c.biancheng.net/shell/
已經進行了三次改版

總結

如果你嘗試在指令碼嵌入一小塊多行資料,使用 Here Document 是很有用的,而嵌入很大的資料塊是一個不好的習慣。你應該保持你的邏輯(你的程式碼)和你的輸入(你的資料)分離,最好是在不同的檔案中,除非是輸入一個很小的資料集。

Here Document 最常用的功能還是向使用者顯示命令或者指令碼的用法資訊,例如類似下面的函數:
usage(){
    cat <<-END
        usage: command [-x] [-v] [-z] [file ...]
        A short explanation of the operation goes here.
        It might be a few lines long, but shouldn't be excessive.
END
}