2.3 一個簡單的腳本
who命令可以告訴你現在系統有誰登陸:
- [root@localhost ~]# who
- root pts/2 2012-05-05 09:38 (192.168.0.83)
- root pts/3 2012-05-05 09:38 (192.168.0.83)
利用wc(字數計算)程序,它可以算出行數(line),字數(word),字符數(character)。在此例中,我們用的是wc -l
- [root@localhost ~]# who|wc -l
- 2 //計算用戶個數
|(管道)符號可以在兩個程序之間建立管道(pipeline):who的輸出,成了wc的輸入,wc所列出的結果就是已登錄用戶的個數
下一步則是把管道轉變成一個獨立的命令。方法是把這條命令輸入一個一般的文件中,然後使用chmod爲該文件設置執行權限,如
- [root@localhost ~]# vim test_who //建立文件
- #! /bin/sh -
- who | wc -l //程序的內容
- [root@localhost ~]# chmod +x test_who //讓文件擁有執行的權限
- [root@localhost ~]# ./test_who //執行測試
- 2 //輸出我們要的結果
2.5.2 變量
在Shell的世界裏,變量值可以是(而且通常是)空值,也就是不含任何字符
Shell變量名稱的開頭是一個字母或下劃線符號,後面可以接着任意長度的字母,數字或者下劃線。
- [root@localhost ~]# vim test_var
- [root@localhost ~]#
-
#! /bin/sh -
myvar="hello word"
echo $myvar
echo -n "請輸入參數:"\
echo $PATH - printf "The first program always prints ' %s,%s! ' \n" hello world 11
表 2-2 echo的轉義序列
序列 | 說明 |
\a | 警示字符,通常是ASCII的BEL字符 |
\b | 退格 |
\c | 輸出中忽略最後的換行符(Newline)。這個參數之後的任何字符,包括接下來的參數,都會被忽略掉(不打印) |
\f | 清除屏幕(Formfeed) |
\n | 換行 |
\r | 回車 |
\t | 水平製表符 |
\v | 垂直製表符 |
\\ | 反斜槓字符 |
2.5.4 華麗的printf輸出
printf不像echo那樣會自動提供一個換行符號。你必須顯示地將換行符號指定成\n
第一部分是一個字符串,用來描述輸出的排列方式,最好爲此字符串加上引號。此字符串包含了按 字面顯示的字符(characters to be printed literally)以及格式聲明(format specifications),後者是特殊的佔位符(placeholders),用來描述如何顯示相應的參數(argument)。
第二部分是與格式聲明相對應的參數列表(argument list),例如一系列的字符串或變量值。格式聲明分成兩部分:百分比符號(%)和指示符(specifier)。最常用的格式指示符(format specifier)有兩個,%s用於字符串,而%d用於十進制整數。
程序應該有數據的來源端,數據的目的端(數據要去的地方)以及報告問題的地方,它們分別被稱爲 標準輸入(standard input)、標準輸出(standard output)、以及標準錯誤輸出(standard error)
默認的標準輸入、標準輸出以及標準錯誤輸出都是終端
2.5.5.1 重定向與管道
Shell提供了數種語法標記,可用來改變默認I/O的來源端與目的端
以<改變標準輸入
program < file 可將program的標準輸入修改爲file:
tr -d '\r' < dos-file.txt
以>改變標準輸出
program > file 可將program的標準輸出修改爲file:
tr -d '\r' < dos-file.txt > UNIX-file.txt
這條命令會先以tr將dos-file.txt裏的ASCII carriage-return(回車)刪除,在將轉換完成的數據輸出到UNIX-file.txt。dos-file.txt裏的原始數據不會有變化。
> 重定向符(redirector)在目的文件不存在時,會新建一個。然而,如果目的文件已存在,它就會被覆蓋;原本的數據都會丟失
以>>附加到文件
program>>file可將program的標準輸出附加到file的結尾處。
如同>,如果目的文件不存在,>>重定向符便會新建一個。然而,如果目的文件存在,它不會直接覆蓋掉文件,而是將程序所產生的數據附加到文件結尾處:
以|建立管道
program1 | program2 可將program1的標準輸出修改爲program2的標準輸入。
tr
語法
tr [options]source-char-listreplace-char-list
用途
轉換字符。例如,將大寫字符轉換成小寫。選項可讓你指定所要刪除的字符,以及將一串重複出現的字符濃縮成一個
常用選項
-c
取source-char-list的反義。tr要轉換的字符,變成未列在source-char-list中的字符。此項通常和-d或-s配合使用
-C
與-c相似,但所處理的是字符(可能是包含多個字節的寬字符),而非二進制的字節值。
-d
自標準輸入刪除source-char-list裏所列的字符,而不是轉換它們。
-s
濃縮重複的字符。如果標準輸入中連續重複出現source-char-list裏所列出的字符,則將其濃縮成一個。
行爲模式
如同過濾器:自標準輸入讀取字符,再將結果寫到標準輸出
舉例:
- [root@localhost ~]# vi test1.txt
- test1 1
- test2 2
- test3 3
- test4 4
- test5 5
- [root@localhost ~]# tr -d '\n' < test1.txt
- test1 1test2 2test3 3test4 4test5 5
警告
根據POSIX標準的定義,-c處理的是二進制字節值,而-C處理的是現行locale所定義的字符。
注意:構造管道時,應該試着讓每個階段的數據量變的更小
例如,使用sort排序之前,先以grep找出相關的行;這樣可以讓sort少做些事。
.
2.5.6 基本命令查找
Shell會沿着查找路徑$PATH來尋找命令。$PATH是一個以冒號分隔的目錄列表,你可以在列表所指定的目錄下找到所要執行的命令。
默認路徑(default path)至少包含/bin與/usr/bin,或許還包含存放X Windows程序的/usr/X11R6/bin,以及供本地系統管理人員安裝程序的/usr/local/bin
名稱爲bin的目錄用來保存可執行文件,bin是binary的縮寫,也可以直接把bin解釋成相應的英文字義--存儲東西的容器;
如果你要編寫自己的腳本,最好準備自己的bin目錄來存放它們,並且讓Shell能夠自動找到它們。這不難,只要建立自己的bin目錄,並將它加入$PATH中的列表即可:
- [root@localhost ~]# cd ~
- [root@localhost ~]# mkdir bin
- [root@localhost ~]# mv /usr/
- bin/ include/ lib/ man/ src/ X11R6/
- etc/ java/ libexec/ sbin/ tmp/
- games/ kerberos/ local/ share/ ucb/
- [root@localhost ~]# mv /usr/ucb/nusers ./bin/
- [root@localhost ~]# PATH=$PATH:$HOME/bin
- [root@localhost ~]# nusers
- 1
- [root@localhost ~]#
PATH=$PATH:$HOME/bin
在$PATH裏的空項目(empty component)表示當前目錄(current directory)。空項目位於路徑值中間時,可以用兩個連續的冒號來表示,如果將冒號直接置於最前端或者尾端,可以分別表示查找時最優先查找或最後查找當前目錄:
PATH=:/bin:/usr/bin //先找當前目錄
PATH=/bin:/usr/bin: //最後找當前目錄
PATH=/bin:/usr/bin //當前目錄居中
如果你希望將當前目錄納入查找路徑(search path),更好的做法是在$PATH中使用點號(dot)
空項目在可移植性上有點問題
一般來說,你根本就不應該在查找路徑中放進當前目錄,因爲這會有安全上的問題。