閱讀349 返回首頁    go 阿裏雲 go 技術社區[雲棲]


實用bash命令記錄

本篇文章記錄工作中比較實用,能減輕工作量的bash命令。

1.字符串截取

假設有這麼一個變量silo=/home/liujiacai/codes/cascalog/silo,那麼

${silo##/*/}=silo
${silo#/*/}=liujiacai/codes/cascalog/silo

##表示取後麵字符串最長的那段;#表示取最短的那段,這兩個是從前麵刪除的

${silo%%/*/}=/home/liujiacai/codes/cascalog/silo
${silo%%/*}=       (空)
${silo%/*}=/home/liujiacai/codes/cascalog

%%和##功能相同,不過這個是從後麵開始刪的。第一個什麼也沒刪除是因為silo最後一個字符為‘o’不是‘/’,所以不變

 Bash Shell可以進行變量的條件替換,既隻有某種條件發生時才進行替換

 ${FOO:-word}  

當沒有FOO變量時,返回word

${FOO:=word}

當沒有FOO變量時,返回word,並且把word賦值給FOO變量

 ${FOO:+word}  

當定義了FOO變量時,返回word

${FOO:?msg}

當沒有FOO變量時,把msg送到標準錯誤輸出

${FOO:offset:length} 

length可以為空

${#FOO}

變量FOO字符個數

 ${FOO/pattern/string}

字符串替換,最短原則

 ${FOO//pattern/string}

字符串替換,最長原則

如果FOO=aabbbbbbbcc,那麼

echo ${FOO//bb/dd}返回aaddddddbcc

echo ${FOO//bb/dd}返回aaddbbbbbcc

2.正則表達式

以前在做java開發時也無數次遇到RE(regex expression),每次看我都以為我懂了,直到今天我才算是明白,我掌握的知識永遠是那麼冰山一角。扯蛋完畢。

Warning:正則表達式和通配符(wildcard)不一樣。

正則表達式分基本RE與擴展RE之分,Bash中有個命令默認隻認識基本的,比如grep,但是通過-e參數就能識別擴展的了;有的可以認識擴展,這點一定要搞清楚。

在基本表達式中有這麼幾個特殊字符,一定要記住

基本正則表達式的特殊字符 RE字符 含義與範例 ^word 待搜索的字符串(word)必須在行首 word$ 待搜索的字符串(word)必須在行尾 . 代表任意一個字符 \ 轉移符,將有特殊符號的特殊意義去掉 * 重複前一個字符,一次或多次。WARN:這裏和通配符中*含義不同 \{n,m\} 連續n到m個的“前一個重複字符” [word] []內的字符集合中任取一個字符 h[io]t  代表的是hit或者hot;其次是[0-9]、[a-z]等這種用法; 再其次是[^word],表示不含“w”、“o”、“r”、“d”中的字符

再說說擴展RE的特殊字符

擴展正則表達式的特殊字符 RE字符 含義與範例 + 重複前一個字符一次或一次以上,比如go+d,,可以表示god、good、goood等等 重複前一個字符零次或一次,比如go?d,表示gd、god | 表示或的意思,比如'gd|good',表示取gd或者good () 分組處理字符,比如'g(la|oo)d',可以表示glad或者good

再提醒一次,“!”歎號在正則表達式中並不是特殊字符。

Unix-like係統還存在一類字符串匹配機製--globbing,在globbing中,*和通配符的用法是一樣的,代表零個或多個任意字符。git的.gitignore文件就是使用的這種字符串匹配模式

詳情參見:https://en.wikipedia.org/wiki/Glob_(programming)

3.find命令

find path [-name] pattern  在path路徑下查找名字為pattern的文件,返回基於path的相對路徑

find . -type f -exec file '{}' \;
這條命令查找當前目錄下的文件,並且作為file命令的參數執行。{}表示當前文件名,用單引號是防止{}被shell解釋器解釋為shell script punctuation,分號用反斜線也是這樣目的,也可以用單引號代替反斜線。
find $HOME -mtime 0
查找$HOME文件夾下在24小時之內修改過的文件。這裏用0是因為-mtime選項對於每個文件的修改時間取其除以24後的商,餘數舍棄。

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
-print -prune
這個命令是用來查看項目的是否有.svn與.git與CVS目錄的,-o 是-or的簡寫,表示前麵的命令為false時才執行,{}表示當前處理的文件夾名,-prune選項可以防止不必要的嵌套查找,假設repo有如下目錄結構:

repo/project1/CVS
repo/gnu/project2/.svn
repo/gnu/project3/.svn
repo/gnu/project3/src/.svn
repo/project4/.git

帶上-prune選項後就不會再搜索project3/.src目錄了,因為已經找到了project3/.svn了。

4.xargs

這個命令在管道中特別有用

  find /tmp -name core -type f -print | xargs /bin/rm -f 
這條命令查找/tmp文件夾下名為core的文件,並且把它刪除。這時的文件名中不能有空格、換行符,解決方法是加上 -0參數。

當然上麵這條命令還可以這麼寫:

 find /tmp -depth -name core -type f -delete
 
利用find的參數-delete選項,這樣比用xargs效率更高,因為這樣不用再調用 fork(2) and exec(2) 來launch rm和xargs進程。

這裏的-depth選項指明“先處理文件夾中的內容在處理文件夾本身”,-delete本身就暗含了-depth選項。

<span >cut -d: -f1 < /etc/passwd | sort | xargs</span>
這條命令用於顯示passwd文件中記錄的當前係統的用戶。

需要注意的時,xargs並不能一定保證,命令正確執行,有可能xargs後麵的命令在接受管道前麵的輸入時,係統執行其他命令,改變了xargs的輸入。


5. bash中的比較

bash中有個test命令可以進行一係列的測試,man 一下可以看到解釋為" check file types and compare values",具體語法為

test EXPRESSION
其實我們最常用的是test的一個別名"[",沒錯,就是左方括號,語法為

[ EXPRESSION ]

EXPRESSION後麵的右方括號是作為結束隻用,沒什麼實際含義.

如果忽略EXPRESSION,那麼返回false. 常用的EXPRESSION有如下這麼幾個:

( EXPRESSION )
      EXPRESSION is true  需要注意一點的是,括號"(",")"需要用"\"轉義
! EXPRESSION
      EXPRESSION is false
EXPRESSION1 -a EXPRESSION2
      both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2
      either EXPRESSION1 or EXPRESSION2 is true
-n STRING
      the length of STRING is nonzero.STRING equivalent to -n STRING
-z STRING
      the length of STRING is zero
STRING1 = STRING2
      the strings are equal
STRING1 != STRING2
      the strings are not equal
INTEGER1 -eq INTEGER2
      INTEGER1 is equal to INTEGER2
INTEGER1 -ge INTEGER2
      INTEGER1 is greater than or equal to INTEGER2
INTEGER1 -gt INTEGER2
      INTEGER1 is greater than INTEGER2
INTEGER1 -le INTEGER2
      INTEGER1 is less than or equal to INTEGER2
INTEGER1 -lt INTEGER2
      INTEGER1 is less than INTEGER2
INTEGER1 -ne INTEGER2
      INTEGER1 is not equal to INTEGER2
FILE1 -ef FILE2
      FILE1 and FILE2 have the same device and inode numbers
FILE1 -nt FILE2
      FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2
      FILE1 is older than FILE2
-d FILE
      FILE exists and is a directory
-e FILE
      FILE exists

test的這些Express和我們平常用的C/Java語言係列的判斷不一樣(比如需要對一些字符進行轉義),這點讓我們很不是適應,不過幸好,bash提供了補救方案,那就是"[[",使用"[["可以對文件名和字符串使用更自然的語法。可以用括號和邏輯操作符把 test 命令支持的測試組合起來。下麵給出一個示例:

使用 [[ 複合命令,這裏不再需要對"("與")"進行轉義

[[ ( -d "$HOME" ) && ( -w "$HOME" ) ]] &&  echo "home is a writable directory"

參考:

https://www.ibm.com/developerworks/cn/linux/l-bash-test.html




最後更新:2017-04-03 12:54:36

  上一篇:go [LeetCode]15.3Sum
  下一篇:go DEV GridView顯示行號