|
'!'符號在Linux中不但可以用作否定符號,還可以用來從歷史命令記錄中取出命令或不加修改的執(zhí)行之前運行的命令。下面的所有命令都已經(jīng)在Bash Shell中經(jīng)過確切地檢驗。盡管我沒有試過,但大多都不能在別的Shell中運行。這里我們介紹下Linux命令行中符號'!'那驚人和奇妙的用法。
1. 使用數(shù)字從歷史命令列表中找一條命令來執(zhí)行您也許沒有意識到您可以從歷史命令列表(之前已經(jīng)執(zhí)行的命令集)中找出一條來運行。首先,通過'history'命令查找之前命令的序號。 $ history

使用history命令找到最后執(zhí)行的命令 現(xiàn)在,只需要使用歷史命令輸出中顯示在該命令前面的數(shù)字便可以運行這個命令。例如,運行一個在history輸出中編號是1551的命令。 $ !1551

使用命令ID來執(zhí)行最后運行的命令 這樣,編號為1551的命令(上面的例子是top命令)便運行了。這種通過ID號來執(zhí)行之前的命令的方式很有用,尤其是在這些命令都很長的情況下。您只需要使用![history命令輸出的序號]便可以調用它。
2. 運行之前的倒數(shù)第二個、第七個命令等您可以以另一種方式來運行之前執(zhí)行的命令,通過使用-1代表最后的命令,-2代表倒數(shù)第二個命令,-7代表倒數(shù)第七個命令等。 首先使用history命令來獲得執(zhí)行過的命令的列表。history命令的執(zhí)行很有必要,因為您可以通過它來確保沒有rm command > file或其他會導致危險的命令。接下來執(zhí)行倒數(shù)第六個、第八個、第十個命令。 $ history
$ !-6
$ !-8
$ !-10

通過負數(shù)序號運行之前執(zhí)行的命令
3. 傳遞最后執(zhí)行的命令的參數(shù),以方便的運行新的命令我需要顯示/home/$USER/Binary/firefox文件夾的內容,因此我執(zhí)行: $ ls /home/$USER/Binary/firefox
接下來,我意識到我應該執(zhí)行'ls -l'來查看哪個文件是可執(zhí)行文件。因此我應該重新輸入整個命令么?不,我不需要。我僅需要在新的命令中帶上最后的參數(shù),類似: $ ls -l !$
這里!$將把最后執(zhí)行的命令的參數(shù)傳遞到這個新的命令中。 
將上一個命令的參數(shù)傳遞給新命令
4. 如何使用!來處理兩個或更多的參數(shù)比如說我在桌面創(chuàng)建了一個文本文件file1.txt。 $ touch /home/avi/Desktop/1.txt
然后在cp命令中使用絕對路徑將它拷貝到/home/avi/Downloads。 $ cp /home/avi/Desktop/1.txt /home/avi/downloads
這里,我們給cp命令傳遞了兩個參數(shù)。第一個是/home/avi/Desktop/1.txt,第二個是/home/avi/Downloads。讓我們分別處理他們,使用echo [參數(shù)]來打印兩個不同的參數(shù)。 $ echo '1st Argument is : !^'
$ echo '2nd Argument is : !cp:2'
注意第一個參數(shù)可以使用'!^'進行打印,其余的命令可以通過'![命令名]:[參數(shù)編號]'打印。 在上面的例子中,第一個命令是cp,第二個參數(shù)也需要被打印。因此是'!cp:2',如果任何命令比如xyz運行時有5個參數(shù),而您需要獲得第四個參數(shù),您可以使用'!xyz:4'。所有的參數(shù)都可以通過'!*'來獲得。 
處理兩個或更多的參數(shù)
5. 以關鍵字為基礎執(zhí)行上個的命令我們可以以關鍵字為基礎執(zhí)行上次執(zhí)行的命令。可以從下面的例子中理解: $ ls /home > /dev/null [命令1]
$ ls -l /home/avi/Desktop > /dev/null [命令2]
$ ls -la /home/avi/Downloads > /dev/null [命令3]
$ ls -lA /usr/bin > /dev/null [命令4]
上面我們使用了同樣的命令(ls),但有不同的開關和不同的操作文件夾。而且,我們還將輸出傳遞到/dev/null,我們并未顯示輸出,因而終端依舊很干凈。 現(xiàn)在以關鍵字為基礎執(zhí)行上個的命令。 $ ! ls [命令1]
$ ! ls -l [命令2]
$ ! ls -la [命令3]
$ ! ls -lA [命令4]
檢查輸出,您將驚奇發(fā)現(xiàn)您僅僅使用關鍵字ls便執(zhí)行了您已經(jīng)執(zhí)行過的命令。 
以關鍵字為基礎執(zhí)行命令 (LCTT 譯注:澄清一下,這種用法會按照命令名來找到最后匹配的命令,不會匹配參數(shù)。所以上述執(zhí)行的四個命令都是執(zhí)行了 ls -lA /usr/bin > /dev/null,并增加了新的參數(shù)而已。)
6. !!操作符的威力您可以使用(!!)運行/修改您上個運行的命令。它將附帶一些修改/調整并調用上個命令。讓我給您展示一些實際情境。 昨天我運行了一行腳本來獲得我的私有IP,因此我執(zhí)行了: $ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/
接著,我突然發(fā)現(xiàn)我需要將上面腳本的輸出重定向到一個ip.txt的文件,因此,我該怎么辦呢?我該重新輸入整個命令并重定向到一個文件么?一個簡單的解決方案是使用向上光標鍵并添加'> ip.txt'來將輸出重定向到文件。 $ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/ > ip.txt
在這里要感謝救世主'向上光標鍵'?,F(xiàn)在,考慮下面的情況,這次我運行了下面這一行腳本。 $ ifconfig | grep 'inet addr:' | awk '{print $2}' | grep -v '127.0.0.1' | cut -f2 -d:
一旦我運行了這個腳本,Bash提示符便返回了錯誤消息'bash: ifconfig: command not found'。原因并不難猜,我運行了本應以root權限的運行的命令。 所以,怎么解決呢?以root用戶登錄并且再次鍵入整個命令就太麻煩了!而且向上導航鍵也不管用了(LCTT 譯注:當你以新的用戶身份登錄了,是不能用向上光標鍵找到之前的另外一個用戶的命令歷史的)。因此,我們需要調用'!!'(去掉引號),它將為那個用戶調用上個命令。 $ su -c !! root
這里su是用來切換到root用戶的,-c用來以某用戶運行特定的命令,最重要的部分是!!,它將被替換為上次運行的命令。當然!您需要提供root密碼。 
!!操作符的威力 我通常在下面的情景中使用!!。 當我用普通用戶來運行apt-get,我通常收到提示說我沒有權限來執(zhí)行。 $ apt-get upgrade && apt-get dist-upgrade
好吧,有錯誤。但別擔心,使用下面的命令來成功的執(zhí)行... $ su -c !!
同樣的適用于: $ service apache2 start
或 $ /etc/init.d/apache2 start
或 $ systemctl start apache2
普通用戶不被授權執(zhí)行那些任務,這樣相當于我運行: $ su -c 'service apache2 start'
或 $ su -c '/etc/init.d/apache2 start'
或 $ su -c 'systemctl start apache2'
(LCTT 譯注:使用!!之前,一定要確認你執(zhí)行的是什么命令!另外,在 root 身份下,千萬不要養(yǎng)成使用它的習慣,因為你總是會在不合適的目錄執(zhí)行不合適的命令?。?/p>
7.運行一個影響所有除了![FILE_NAME]的文件命令!(邏輯非)能用來對除了'!'后的文件的所有的文件/擴展名執(zhí)行命令。
A.從文件夾移除所有文件,2.txt除外。 $ rm !(2.txt)
B.從文件夾移除所有的文件類型,pdf類型除外。 $ rm !(*.pdf)
8.檢查某個文件夾(比如/home/avi/Tecmint)是否存在?并打印這里,我們使用'! -d'來驗證文件夾是否存在,當文件夾不存在時,將使用其后跟隨AND操作符(&&)進行打印,當文件夾存在時,將使用OR操作符(||)進行打印。 邏輯上,當[ ! -d /home/avi/Tecmint ]的輸出為0時,它將執(zhí)行AND邏輯符后面的內容,否則,它將執(zhí)行OR邏輯符(||)后面的內容。 $ [ ! -d /home/avi/Tecmint ] && printf '\nno such /home/avi/Tecmint directory exist\n' || printf '\n/home/avi/Tecmint directory exist\n'
9.檢查某文件夾是否存在?如果不存在則退出該命令類似于上面的情況,但這里當期望的文件夾不存在時,該命令會退出。 $ [ ! -d /home/avi/Tecmint ] && exit
10.如果您的home文件夾內不存在一個文件夾(比方說test),則創(chuàng)建它這是腳本語言中的一個常用的實現(xiàn),當期望的文件夾不存在時,創(chuàng)建一個。 [ ! -d /home/avi/Tecmint ] && mkdir /home/avi/Tecmint
這便是全部了。如果您知道或偶爾遇到其他值得了解的'!'使用方法,請您在反饋的地方給我們提建議。保持聯(lián)系!
|