SHELL複習摘要(三)
擴展性樣式比對
shell於egrep/awk正則表達式運算符比較
ksh/bash egrep/awk 含義
*(exp) exp* 存在0個或多個exp
+(exp) exp+ 存在1個或多個exp
?(exp) exp? 存在0個或1個exp
@(exp1|exp2|…) exp1|exp2|… exp1或exp2
!(exp) (none) 所有不相符於exp的
例如:
@(dave|fred|bob)比對相符的有dave、fred、bob
*(dave|fred|bob)意即存在0或多個dave等
+(dave|fred|bob)相符於上述所有字符串,null除外
?(dave|fred|bob)相符於null字符串,dave等
!(dave|fred|bob)相符於dave、fred、bob之外的任何字符串
egrep和awk有兩個正則表達式運算符在shell裏沒有等同物:
行開否與行結束運算符^和$。
單詞的起始與單詞的結束運算符\<與\>
括弧展開
括弧展開式讓輸入更輕鬆的方法
echo cpp-{args,l{e,o}x,parse}.c
cpp-args.c cpp-lex.c cpp-lox.c cpp-parse.c
進程替換
進程替換可以讓用戶開啓多個進程數據流,再將它們餵給單一程序處理。
例如:
awk ‘…’ <(generate_data) <(generate_more_data)
進程替換也可用於輸出,特別是配合tee使用。
cat generate_data |tee >(sort | uniq |wc -l) >(grep “USER”|wc -l)>/dev/null
進程替換只有在支持/dev/fd/n特殊文件的UNIX系統下可使用,爲命名訪問到已開啓之文件描述代碼。
各類擴展
附加的波浪號展開:POSIX將~定義爲$HOME與~user—user家目錄。bash和ksh允許使用~+作爲$PWD(當前工作目錄)的縮寫,使用~-作爲$OLDPWD(前一個工作目錄)的縮寫。
算術命令:POSIX定義$((…))標記作爲算術展開,但不提供任何其他算術操作限制。不過兩種shell都支持兩種直接處理算術的標記,而非展開:
let “x = 5+y” let命令,需以引號框起
((x = 5+y)) 未前置$,自動的用雙括號引起來
x=$((5+y)) 類似,但=前後都不可置放任何空格
有個不同之處,便是let與((…))都有離開狀態:0爲真(true)值,而1爲僞(false)值。
case語句的可選用圓括號比對:命令替換的$(…)語法已由POSIX標準化。case開啓圓括號必須置於$(…)內。
some command $(…
case $var in
( foo|bar ) some other command ;;
( stuff|junk ) something else agin ;;
esac
…)
使用<<<的即席字符串:以echo產生單行輸入供進一步處理,是相當常見的用法。
例:echo $myvar1 $myvar2 |tr …|…
即席字符串使用<<<再接上字符串。字符串即成爲相關聯命令的標準輸入,輔以shell自動提供最後的換行符號:
tr … <<< “$myvar1 $myvar2”|…
擴展性字符串標記:此標記包括在單引號框起的字符串,前置一個$。這類字符串的行爲模式像一般單引號框起來的字符串,不過shell會解釋字符串裏的轉義符。
echo $’A\tB’
A B
EXPECT交互
#!/usr/bin/expect
set timeout 30
spawn ssh [email protected]
expect "password:"
send "Scctwap#2010\r"
expect "#"
send "df -h\r"
expect eof
interact
算術計算
let、bc、dc、expr、echo和awk
let “t2=((a=1,15/3))”#set a=1,t2=5
逗號鏈接了一系列的算術操作,雖然裏邊所有的內容都被運行了,但只有最後一項被
返回
bc是一個交互式計算器,通過管道可以不交互
# echo "(6+3)*2" |bc
18
# echo 15/4 |bc
3
# echo "scale=2;15/4" |bc
3.75
# echo "3+4;5*2;5^2;18/4" |bc
7
10
25
4
dc是比bc更復雜的交互式計算器,他是壓棧操作。
# dc
3
2+
p
5
4*
p
20
quit
# echo 3 2+ 4* p |dc
20
expr不光可以計算加減乘除,還有表達式。需要空格和轉義符號
# expr length "yangzhigang.cublog.cn"
21
#expr 3 + 2
5
echo可以簡單計算
#echo $(((2+3)*2))
10
Awk也可以進行簡單計算
#awk ‘BEGIN{a=2+3;print a}’
5
bash腳本安全開場白
IFS=$’ \t\n’
unset –f unalias
unset –f command
SYSPATH=”$(command –p getconf PATH 2>/dev/null)”
if [[ -z “$SYSPATH” ]];then
SYSPATH=”/usr/bin:/bin”
fi
PATH=”$SYSPATH:$PATH”
:空命令
空命令,等價於"NOP"(no op,一個什麼也不幹的命令).也可以被認爲與shell 的內建命令(true)作用相同.":"命令是一個 bash 的內建命令,它的返回值爲0,就是shell 返回的true.
在一個 2 元命令中提供一個佔位符,具體見Example 8-2,和"默認參數".如:
1 : ${username=`whoami`}
2 # ${username=`whoami`} 如果沒有":"的話,將給出一個錯誤,除非"username"是
3 # 個命令
使用"參數替換"來評估字符串變量.如:
1 : ${HOSTNAME?} ${USER?} ${MAIL?}
2 # 如果一個或多個必要的環境變量沒被設置的話,
3 #+ 就打印錯誤信息.
"變量擴展/子串替換"
在和 > (重定向操作符)結合使用時,把一個文件截斷到0 長度,沒有修改它的權限.
如果文件在之前並不存在,那麼就創建它.如:
1 : > data.xxx #文件"data.xxx"現在被清空了.
2
3 #與 cat /dev/null >data.xxx 的作用相同
4 #然而,這不會產生一個新的進程,因爲":"是一個內建命令.
在和>>重定向操作符結合使用時,將不會對想要附加的文件產生任何影響.
如果文件不存在,將創建.
注意: 這隻適用於正規文件,而不是管道,符號連接,和某些特殊文件.
:應用技巧,可以產生自文檔化腳本
1 #!/bin/bash
2 # self-document.sh: 自文檔化(self-documenting)的腳本
3 # Modification of "colm.sh".
4
5 DOC_REQUEST=70
6
7 if [ "$1" = "-h" -o "$1" = "--help" ] # 請求幫助.
8 then
9 echo; echo "Usage: $0 [directory-name]"; echo
10 sed -n -e '/DOCUMENTATIONXX$/,/^DOCUMENTATIONXX$/p' "$0" |
11 sed -e '/DOCUMENTATIONXX$/d'; exit $DOC_REQUEST; fi
12
13
14 : <<DOCUMENTATIONXX
15 List the statistics of a specified directory in tabular format.
16 ---------------------------------------------------------------
17 The command line parameter gives the directory to be listed.
18 If no directory specified or directory specified cannot be read,
19 then list the current working directory.
20
21 DOCUMENTATIONXX
22
23 if [ -z "$1" -o ! -r "$1" ]
24 then
25 directory=.
26 else
27 directory="$1"
28 fi
29
30 echo "Listing of "$directory":"; echo
31 (printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n" \
32 ; ls -l "$directory" | sed 1d) | column -t
33
34 exit 0
雙括號結構
使用雙括號後可以使用C風格的變量操作的一種機制。
((a++)) #C風格的計算後自加
((++a)) #C風格的計算前自加
((t=a<10?7:11)) #C風格的三元計算,如果a小於10,則t等於7,否則t等於11