200 likes | 366 Views
UNIX 工具 簡介. 國立暨南國際大學 計算機與網路中心 研究助理 張克寧 klim@ncnu.edu.tw. 正規表示法 (regular expression). 以 am 開頭, tion 結尾的字 $ grep ' ^ am.*tion $ ’ /usr/share/lib/dict/words ambition ammunition 包含 abc 的字 $ grep 'abc' /usr/share/lib/dict/words abc Babcock. 正規表示法 (regular expression).
E N D
UNIX 工具簡介 國立暨南國際大學 計算機與網路中心 研究助理 張克寧 klim@ncnu.edu.tw
正規表示法(regular expression) • 以 am 開頭,tion結尾的字 $ grep '^am.*tion$’ /usr/share/lib/dict/words ambition ammunition • 包含 abc 的字 $ grep 'abc' /usr/share/lib/dict/words abc Babcock
正規表示法(regular expression) • c, \c --> 匹配字元‘c’ • . -->匹配任何字元 • [abc], [a-zA-Z] --> 任何其中一個字元 • [^abc] --> 任何不屬於其中的一個字元 • a?, a+, a*, a[n], a[n,m], a[,m], a[n,]: • a(b|c)*d
正規表示法練習 • 下述式子的執行結果為何 • grep '^\([^:]*\):.*:[^:]*\1:[^:]*$' /etc/passwd • 找出包含ex並以tion結尾的字 • 找出不包含母音的字 • 找出不包含母音及 ‘ 的所有小寫的字
vi • command mode v.s. insert mode • 游標移動: • , hjkl • PageUp,PageDown, ^F^B, ^D^U • [n]G: 到指定的行 • [n]|: 到指定的列 • wb: 移至下(上)一個字 • 0,$: 行首, 行尾
vi • insert mode: • i,a:在目前的字元前(後)插入 • I,A:在此行的最前(後)面插入 • o,O:在此行的下(上)面插入 • 離開 insert mode: ESC • 刪除,複製: • [n]x,[n]X:從游標往後(前)刪除目前 n 字元 • [n]dd: 從本行開始刪除 n 行 • [n]yy: 從本行開始複製n 行 • p, P: 貼在游標的後(前)面
vi • 檔案: • :w 儲存 • :q 跳出 • :wq 儲存且跳出(與 ZZ 相同) • :q! 強制跳出 • ex (:) 指令 :line1,line2c args • :.,$w xxx 將本行至最後儲存至檔案 xxx • :set nu, :set nonu (不)顯示行號 • :set all 所有參數
vi • search, replace: • /,?: 往前(後)搜尋 • n,N: 以同(反)向重複上一個搜尋 • :set ws, :set nows 是否 wrap scan • :1,$s/xxx/yyy/g 從第一行至最後一行把所有的 xxx 換成 yyy
vi 練習 • 下列命令有何動作: • 15i?ESCh • i15?ESCh • i?ESC15h • 在第一行及最後一行按 ^G 結果為何? • 如何在每一行的最前面插入 “>”
file stdin file stdout sed: s/pattern/replace/ 行, 行... 行, 行... awk: pattern1 {action1} pattern2 {action2} …... sed, awk $sed -e ‘s@:@@g’ /etc/passwd > ppp $awk -F: ‘{print $1 “ “ $NF}’ /etc/passwd
awk #!/usr/bin/nawk -f BEGIN { samplespace = "abcdefg2hi34jk56mn7p8qr99stuvwxyz23456789" sampleno = length(samplespace) srand() } function passwd() { password = "" for(j=0; j<8; j++) { password = password substr(samplespace, rand()*sampleno, 1) } return password } /^ *$/ {} /^ *#/ {print $0} /^ *[^#]/ { if ( NF == 3 ) print $1 " " $2 " " $3 else print $1 " " $2 " " passwd() } 變數 字串相加 $0:整行, $1,$2…第n個欄位 內定變數, NF: 欄位數
awk $ cat userlist # 七龍珠 孫悟空 monkey 賽亞人 saiya super $ ./pwdgen userlist # 七龍珠 孫悟空 monkey 8fbf4f7z 賽亞人 saiya super $ 空行 註解
+ # name1 123 345 # name2 333 444 ... name1: 468 name2: 777 ... + awk 練習 • 若一檔案內每行只有一個數字, 試計算其總和. 若每行有二個數字, 試分別計算第一個欄位及第二欄位的總和及平均. • 試著讀入下列左邊的檔案格式而輸出右邊的格式
sh = 兩邊不能有空白 • 變數: $ a=123 $ b=456 $ echo $a 123 $ echo ${a:-789} 123 $ unset a $ echo ${a:-789} 789 $ echo ${a:-$b} 456 $ a=xxx $ echo ${a:-$b} xxx $ 若 a 無定義或 null 則為 789 若 a 無定義或 null 則為變數 b
sh • 算術: 外部程式 expr $ expr 1 + 2 3 $ expr 2 * 3 expr: syntax error $ expr '2 * 3' 2 * 3 $ expr 2 '*' 3 6 $ a=1 $ a=`expr $a + 1`; echo $a 2 $ w=`pwd`; echo $w /home/klim $ expr $w : '.*' 10 $ expr $w : '.*/\(.*\)' klim $ “(double quote): 變數代換 `(back quote): 什麼都不做 ‘(single quote) :執行程式 命令分隔 傳回匹配的字元數 傳回匹配的字串
sh 檔案形態測試 • 外部程式 test $ test -f flist; echo $? 0 $ test -d flist; echo $? 1 $ test -d PRINT; echo $? 0 $ test "123" -lt "345"; echo $? 0 $ test "x$a" = "x"; echo $? 1 $ echo $a 2 $ a= $ test "x$a" = "x"; echo $? 0 $ if [ -d PRINT ]; then ls PRINT; fi prune.awk prune.awk.orig top $ 上一個命令的 exit 值 0 為 true, 其它為 false 數字比較 字串比較 呼叫 test
sh • flow control: • if commands; then commands; else commands; fi • for var in words; do commands; done • while commands; do commands; done • case string in pattern1|pattern2) commands ;; ... esac
sh and /etc/init.d/sendmail (edited for presentation) case $1 in 'start') if [ -f /usr/lib/sendmail -a -f /etc/mail/sendmail.cf ]; then if [ ! -d /var/spool/mqueue ]; then # some operation about mail queue fi /usr/lib/sendmail -bd -q1h if /usr/sbin/mount -p | /usr/bin/nawk ' BEGIN { s = 1; } $3 == "/var/mail" && $4 == "nfs” && “test more” { s = 0;} END { exit s; }’; then # warning about NFS mounted without actime=o fi fi ;; 'stop') pid=`/usr/bin/ps -eo pid,comm | /usr/bin/awk '{ if ($2 == "/usr/lib/sendmail") print $1 }’` if test "$pid”; then kill $pid fi ;; *) echo "usage: /etc/rc2.d/S88sendmail {start|stop}” ;; esac negate
sh $#: 參數個數 #! /bin/sh if [ $# -lt 1 ] ; then echo "$0 command-names " exit 1 fi findall='TRUE' for f in $* ; do found='FALSE' for d in `echo $PATH | sed 's@:@ @g'` ; do if [ -x "$d/$f" -a ! -d "$d/$f" ] ; then echo "$d/$f" found='TRUE' fi done if [ $found = 'FALSE' ]; then echo $f not found findall='FALSE' fi done exit `test $findall = 'TRUE'` $0: 程式名稱 $*: 所有參數 $ echo $PATH /home/klim/bin:/usr/local/bin: /usr/sbin:/usr/bin:/usr/ucb $ which ls /usr/local/bin/ls /usr/bin/ls /usr/ucb/ls $
sh 練習 • 印出所有小於 100 的 Fibonacci number • 0,1,1,2,3,5… (Fn = Fn-1 + Fn-2) • 將現在目錄的所有結尾為 .a 的檔案更名為 .b, 例如: f1.a f1.b, f2.a f2.b … (參考 basename) • 如何將檔名換成大寫(參考tr ), 寫一程式將從參數傳入的檔名換成大寫, 例如: $ upper A B C 的結果相當於 $ mv A a; mv B b; mv C c