從PATH說起的shell命令行替換

許久之前,師弟問了我一個問題,為什么shell中添加環(huán)境變量的寫法是下面這種方式

PATH=~/.lib:$PATH; export PATH

而下面這種會報錯呢?

$PATH=~/.lib:$PATH; export PATH

當時我的回答是,"shell就是這樣子規(guī)定的呀"。 回答的同時,也突然間發(fā)現有些自己感覺很熟悉的概念,原來自己并沒有那么清楚,因此這一篇講講shell的命令行替換。先說結論

shell會在命令執(zhí)行前對命令行進行一些替換

shell替換有如下幾種:

替換 語法 含義
歷史 ! 之前使用命令
大括號 {} 指定的文本
代字號 ~username 用戶的主目錄
變量 $, ${...} shell和環(huán)境變量
算術 $((..)) 整數運算
命令替換 `...`, $(...) 運行在子shell里命令的輸出
路徑名 *,?,[...],[^...] 文件系統(tǒng)中匹配的文件名

歷史替換是以!開頭的替換方式,以下面歷史記錄為例

歷史記錄
$ !! # 執(zhí)行上一個命令,即history
$ !1021 # 支持第1021個命令 即ls
$ !-2 # 執(zhí)行倒數第二個命令,即ls

大括號替換: 它會將{...}里的內容展開為多個單詞,可以快速創(chuàng)建有一定規(guī)律的文件. 下面這個命令就把"chap0{1..3}"替換成了chap01, chap02, chap03, 以及每個都還有一個html和text對應。

$ mkdir -p chap0{1..3}/{html,text}
$ tree chap0*
chap01
├── html
└── text
chap02
├── html
└── text
chap03
├── html
└── text

代字號代替: 我們經常會看到別人文章會寫用vim ~/.bashrc修改家目錄下的配置文件,其中~默認就會替代成自己家目錄路徑,可以用echo ~確認。

那么問題來了,如何我想快速到別人的家目錄下,應該怎么操作。只要在~加上別人的用戶名就行了。比如說我/home 下還有一個用戶叫做abc, 那么查看它家目錄下的內容就是

ls ~abc

注: ~a可以用tab補全成~abc

變量替換: shell會把${變量名}或者$變量名替換成變量所指代的具體字符,比如說我將abc指代為ls,那么shell就會將$abc解釋成ls,然后執(zhí)行ls

abc=ls
$abs
# Desktop  bin  biosoft  blastdb  miniconda3  ncbi

也就是$PATH=~/.lib:$PATH; export PATH報錯的原因是,shell在執(zhí)行命令前會把$PATH成原來PATH里的字符串,顯然無法達到修改PATH的目的

算術替換: shell命令行支持整數型的數學運算,下面的運算都是可以的,但是就別拿100/2.5這種浮點運算為難shell了。

echo $((1+2))
echo $((1-2))
echo $((100*101))
echo $((100/50))

命令替換:這個替換非常的實用,可以將shell命令的輸入結果立刻作為輸入,而不是額外創(chuàng)建一個變量命。有一個應用場景就是在的分析報告里加上完成時間點

touch reports.$(date +%d%b%Y).log

路徑名替換:路徑替換的語法就4種,*表示0或更多的任意字符,?表示一個任意字符,[...]表示括號內的字符之一,[^...]不包括括號內的字符

以上就是shell命令行替換的幾種形式。當然為了再一次強調"shell會在命令執(zhí)行前對命令行進行一些替換",下面舉一個反面例子來說明下。

Linux的/etc目錄下有很多以conf結尾的配置文件,我們可以用find命令快速的定位到它們。

find /etc -name *.conf

上面的命令看起來沒啥毛病,但是只要多做一件事情,就會有報錯哦

touch a.conf b.conf
find /etc -name *.conf
# 如下是報錯
find: paths must precede expression: b.conf
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec|time] [path...] [expression]

你會不會好奇,明明是相同的命令,卻又不同的境遇呢?讓我解釋下,在剛開始的時候,文件下面沒有"a.conf","b.conf",盡管shell看到"*"會有一種進行通配的沖動,但是很可惜沒有對象讓它統(tǒng)配。后來我們創(chuàng)建了這兩個文件,給shell找到通配的機會,于是實際執(zhí)行的命令就成了 "find /etc -name a.conf b.conf"。 由于后面這兩個是文件路徑,不符合find的命令要求,就導致了報錯。

其實報錯還好,有些時候沒有報錯,程序運行得到錯誤的結果反而更慘

如何避免這種錯誤呢?我們就需要用到"避免\*這個元字符被shell解釋。

除了雙引號,避免shell進行替換的符號還有 反斜杠\ , 和單引號 '. 單引號和雙引號的區(qū)別在于,單引號內部所有字符都是普通字符而已,而雙引號里的美元符號$, 感嘆號! 和反引號 ` 還能被shell解釋

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容