感嘆號 bash 的歷史擴充套件功能

2021-09-23 16:06:44 字數 3889 閱讀 8830

bash 的歷史擴充套件(history expansion)又被稱為 bang(!) 命令,歷史擴充套件是 bash 將歷史命令轉換到可執行命令的過程。bash 下的 history 庫提供了乙個與 csh 下歷史擴充套件類似的歷史擴充套件功能。歷史擴充套件中操作歷史命令一般有兩個部分:

首先要從歷史命令中找出相對應的命令,被選擇到的命令我們稱作為event(條目),比如bang bang(!!),就是選擇最後一條命令;

選擇選定行的部分或全部文字以包含到當前行中。要操作的條目(event)bash將其拆分成了words(詞),命令中的words是靠空格來分割的,我們就可以使用修飾符(modifiers)來調整words以符合我們的要求。注意:words並不是英文單詞,而是乙個字串行而已。

先來看兩個命令,你知道第二個命令是什麼意思麼?

cat

/tmp

/cat

.cat

.txt

!:

0!*:gs/

cat./

echo

.

條目標誌符是乙個到歷史列表內乙個命令列實體的引用,除非是絕對引用,不然條目的引用是相對歷史列表中當前位置的。

條目標誌符

條目標誌符說明

!開始乙個歷史替換,除非後面緊跟的是空格,製表符,行結束符,"=","("(當使用內建命令shopt開啟了extglob的shell選項)。

!n重複歷史中編號為n的命令——歷史編號可以參看history命令.

!-n執行之前的第n條命令,執行上一條命令可以使用!!或者!-1,執行之前第三條命令:!-3,倒推的列表是history

!!執行上一條命令,和ctrl-p,!-1的作用一樣。

!string執行最近的以string字串開頭的命令。這個命令的意思是重複以!後字串開頭的最後一條命令,比如:!ca將重複以字元ca開頭的最後一條命令,如cat readme,(假設最近一條ca開頭是這個命令,並且readme後緊跟換行符)

!?string[?]在歷史列表中以當前位置開始向後查詢(往回搜尋)包含string字串的最近一條命令,如果要查詢的string字串後面緊跟換行符,則string後面的這個問號可以省略。例如:!?read?還是會匹配cat readme。(同上的環境),如果後面是換行符如:!?readme,則不用輸入結尾的[?]。

^a^b快速替換,把上一條命令中的a替換成b,並執行替換後的命令。^a^b^類似。注意:這裡只是替換乙個找到的例項,相當於:!!:s/a/b

^abc刪除上一條命令中的abc。

!#引用目前輸入的所有字串,如:more a !#;這個最終的命令是more a more a

詞標誌符被用來在條目裡面選擇需要的詞。一般用":"分隔條目指示符和詞指示符。當詞指示符是以"^","$","*","-","%"開頭時,也可能會省略":"。詞是從一行的行首開始,第乙個詞編號為0.插入到當前行中時,這些詞使用單個空格分隔。

詞標誌符

詞標誌符說明

0第0個詞,在很多應用程式中,這就是命令本身。

n第n個詞

^第乙個引數;也就是第乙個詞。

$最後乙個引數。

%最近"?string?"匹配的詞。

x-y詞的範圍:如果是'0-y'可以簡寫成'-y'.

*除了第0個以外的所有詞,這個和'1-$'同義,如果條目中只有乙個詞,使用'*'也不會返回錯誤,僅是返回乙個空字串而已。

x*'x-$'的簡寫

x-和x*類似,都是'x-$'的簡寫,不過需要注意,這個寫法是忽略最後乙個詞的。

需要注意的是,在bash下使用詞指示符的時候,可以沒有條目指示符,如果沒有使用條目指示符,則會把前一條命令作為詞指示符的操作條目。

在可選的詞指示符之後,你可以新增下面修飾符中的乙個或多個,每個修飾符以':'開頭。

修飾符修飾符說明

h去掉路徑名的尾部,只保留頭部。只移除最後乙個'/'後面的內容,可以理解成是路徑名的父目錄。

t去掉路徑名部件中除尾部之外的所有內容。只保留最後乙個'/'後的內容。

r去掉尾部這樣格式".suffix"的乙個結尾字尾,保留基本名稱。只刪除最後乙個點'.'後的內容。

e僅保留字尾。僅保留最後乙個點'.'及點後的內容。

p列印新的命令但不執行。

q引用替換的詞,防止進一步替換。(譯註,原文:quote the substituted words, escapin further substitutions.——mitchell chu)。這個引用會直接對引用的命令加上單引號,防止進一步替換。開始這句不知道怎麼翻譯。後來mitchell發現自己的這個翻譯並沒有錯誤,因為我們引用的詞可能是個變數,這時候如果沒有引號,就會引起進一步的替換,而是用此引數就能達到防止這種情況的發生。

x這個和q一樣,是引用替換的詞,但是這個與q不同的地方在於,q是整體引用,而這個是會將替換的詞使用空格,製表符,換行符來分割成乙個個的詞。

s/old/new/把條目行中找到的第乙個old位置的內容替換成new位置的內容,'/'這個分隔符位置可以使用任何其他字元作為分隔符。如果要在old或new位置使用分隔符,需要使用反斜桿'\'來轉義。如果'&'這個字元出現在new位置,將會被替換成old位置的內容,如果要使用'&'請用'\'轉義。最後乙個分隔符如果是整行的最後乙個字元,則可以省略。

&重複上次替換。這個是引用最後一次的s/old/new/內容。

g見下,與a相同

a使替換在整個條目中進行,和's'一起使用,例如:!!:gs/old/new/,或者和'&'一起使用。

g對條目中的每乙個詞都執行一次其後的's'修飾符。這個方法在bash 4.1.2下測試並不靠譜。

test

$eee

/tmp

/test

.log

echo

!test:gs

/t/a

/;

##

這個返回的

test

被替換兩次

##

但後面的引數僅替換一次

因此mitchell在想,是不是僅對引數執行一次,而對命令(第0個詞)進行全域性替換。但另外乙個測試,反駁了這個觀點:

aaaaaaaaaaa $aaaaaaa 

/tmp

/aaaaaaaaaaaaa

.log

echo

!aaaa:q

:gs/a

/t/

##

此時,最多的替換出現在!:

0,兩次!

但多次測試結果來看,第零個詞彙被替換最多兩次,其他只替換一次。具體原因暫時未知!

原文發布時間為:2015-06-19

Linux的! 感嘆號

在echo hello world index.html時發現會回顯執行的命令,且index.html檔案中沒有 號 使用echo hello world index.html時發現連同 一起輸出 解決辦法,不使用雙引號,改用單引號echo hello world index.html 或者感嘆號後...

c語言中感嘆號什麼意思 感嘆號的意思

手機評站網今天精心準備的是 感嘆號的意思 下面是詳解!感嘆號有幾種意思 感嘆號有五種意思,分別是 1,表示強烈的感情 例 我真的很高興 無論是喜 怒 哀或樂,只要帶有強烈感情,均會在句尾用嘆號。2,表示命令 祈求 例 求求你 不要離開這個家 3,嘆詞 例 唉 4,敬語 例 恭喜 恭喜 恭喜 是單獨成...

Shell中的感嘆號

事件提示 shell 中!叫做事件提示符,英文是 event designators,可以方便的引用歷史命令,也就是history中記錄的命令 用法 當後面跟隨的字母不是 空格 換行 回車 和 時,做命令替換 n 會引用history中的第n個命令,比如輸入!100,就是執行history列表中的第...