shell腳本語法基礎彙總

單引 雙引 反引用[] [[]]

將命令的輸出讀入一個變量中,可以將它放入雙引號中,即可保留空格和換行符(\n)

out=$(cat text.txt)

輸出1 2 3

out="$(cat text.txt)"

輸出:

1

2

3

--------------[]一般用於算術比較

-gt 大於

-lt 小於

-ge 大於等於

-le 小於等於

邏輯與-a

[ $var1 -eq 0 -a $var2 -gt 2 ]

邏輯或

[ $var1 -eq 0 -o $var2 -gt 2 ]

[ condition ] && action 等價於if...fi

if [ "$LOOK_OUT" -gt "85" ]

if [ -e /home/slynux ]; then

...

fi

-----------------[[]]一般用於字符串比較

if [[ -n $str1 ]] && [[ -z $str2 ]] ;

then

commands;

fi

========================

1、字符串判斷

str1 = str2      當兩個串有相同內容、長度時爲真
str1 != str2      當串str1和str2不等時爲真
-n str1        當串的長度大於0時爲真(串非空) if [[ -n $1 ]]
-z str1        當串的長度爲0時爲真(空串)
str1         當串str1爲非空時爲真

2、數字的判斷

int1 -eq int2    兩數相等爲真
int1 -ne int2    兩數不等爲真
int1 -gt int2    int1大於int2爲真
int1 -ge int2    int1大於等於int2爲真
int1 -lt int2    int1小於int2爲真
int1 -le int2    int1小於等於int2爲真

3 目錄文件的判斷(if [ ])

-r file     用戶可讀爲真
-w file     用戶可寫爲真
-x file     用戶可執行爲真
-f file     文件爲正規文件爲真
-d file     文件爲目錄爲真
-c file     文件爲字符特殊文件爲真
-b file     文件爲塊特殊文件爲真
-s file     文件大小非0時爲真
-t file     當文件描述符(默認爲1)指定的設備爲終端時爲真

3、複雜邏輯判斷

-a         與
-o        或
!        非



  下面是一些使用實例:

#!/bin/sh
myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"

#這裏的-x 參數判斷$myPath是否存在並且是否具有可執行權限
if [ ! -x "$myPath"]; then
mkdir "$myPath"
fi

#這裏的-d 參數判斷$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi

#這裏的-f參數判斷$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi

#其他參數還有-n,-n是判斷一個變量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi

#兩個變量判斷是否相等
if [ "$var1" == "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 not eq $var2'
fi

-----------------獲取名稱.擴展名

file_jpg="sample.jpg"

name=${file_jpg%.*}

輸出sample

file_jpg="sample.jpg"

extension=${file_jpg#*.}

輸出jpg

------------------ time 計算命令執行時間

time command

--------------- 重定向

0 stdin標準輸入

1 stdout標準輸出   

2 stderr標準錯誤

文件打開模式:

> 等同於1> 截斷模式

>>等同於1>> 追加模式

<用於從文件中讀取至stdin 只讀模式

ls + 2> out.txt

stdout不會有任何輸出,因爲錯誤已經重定向到out.txt中了

可以將stderr單獨重定向到一個文件,將stdout重定向到另一個文件:

cmd 2>stderr.txt 1>stdout.txt

將stderr轉換成stdout,使得stderr和stdout都被重定向到同一個文件:

cmd 2>&1 output.txt

或者

cmd &> output.txt

將stderr輸出丟棄

some_command 2> /dev/null

將文件重定向到命令

cmd < file

向log文件中寫入頭部數據

#!/bin/bash

cat <<EOF>log..tt

LOG FILE HEADER

this is a test log file

EOF

-----------------------/dev/null 2>&1

*/1 * * * * root /usr/local/php/bin/php /var/w.php > /dev/null 2>&1


crontab內容:50 18 5-30 * * /script/myscript.sh 1> /dev/null 2>&1
其中 1> /dev/null 2>&1是什麼意思??
dev/null 爲系統垃圾箱
&爲後臺運行
但是 myscript 後面的1 和 /null後面的2 還有 &後面的1是什麼意思?
1代表標準輸出,2代表錯誤信息輸出.
1>/dev/null 就是指將標準輸出定向到空設備,
2>&1,的意思是將錯誤輸出定向到和1一樣的輸出設備,也同樣是空.


換句話說,就是不顯示該程序執行過程中的任何信息


cmd >a 2>a 和 cmd >a 2>&1 爲什麼不同?
cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件會被打開兩遍 ,由此導致stdout和stderr互相覆蓋。
cmd >a 2>&1 :stdout直接送往文件a ,stderr是繼承了FD1的管道之後,再被送往文件a 。a文件只被打開一遍,就是FD1將其打開
他們的不同點在於:
cmd >a 2>a 相當於使用了FD1、FD2兩個互相競爭使用文件 a 的管道;
而cmd >a 2>&1 只使用了一個管道FD1, 但已經包括了stdout和stderr。
從IO效率上來講,cmd >a 2>&1的效率更高。

----------------- 算數運算 let expr

let 可以直接執行基本的算數操作

no1=4

no2=5

let result=no1+no2

echo $result

let no1++

let no1+=6

操作符[] ,expr 和let命令類似

result=$[ no1 + no2 ]

result=$[ $no1 + $no2 ]

result=`expr 3 + 4`

result=$(expr $no1 + 5)

---------------- 浮點運算 bc

#echo "4 * 0.56" | bc

2.24

-----------------獲得字符串長度

var=123456

echo ${#var}

-----------------環境變量$PATH和export

echo $PATH

PATH通常定義在/etc/environment或/etc/profile或~/.bashrc中

export命令用來設置環境變量;

添加新的路徑:

export PATH="$PATH:/home/user/bin"

或者

PATH="$PATH:/home/user/bin"

export PATH

其它環境變量:HOME,PWD,USER,UID,SHELL

查看進程相關的環境變量:

cat /proc/$PID/environ

----------------- printf 格式化輸出

printf "%-5s %-10s %-4s\n" No Name Mark

printf "%-5s %-10s %-4.2f\n" 1 James 91.32

輸出爲:

No Name Mark

1 James 91.32

%-5s 指明瞭一個格式爲左對齊且寬度爲5的字符串替代(- 表示左對齊)

-4.2f 表示對浮點數的處理格式

-------------- 讀取命令返回值$?

cmd;

echo $?;

-------------------------shell 調試

#!/bin/bash -xv 不用任何其他選項就可以啓用調試功能了

sh -n sh16.sh 不執行script,僅查詢語法

sh -x sh16.sh 將script執行過程全部列出來

需要給變量賦值時,可以這麼寫: 
變量名=值 
要取用一個變量的值,只需在變量名前面加一個$

a="hello world"
echo "A is:" $a

//if 注意空格

a=$1

if [[ $a -eq 2 ]] ;then

echo "1"

else

echo "2"

fi

if [[ $a = gjslint ]] ;then

echo "1"

exit 0

else

echo "2"

fi

exit 0

===================== 調用php的sh

#!/bin/bash

if [[ $0 = /* ]]

then

  curfile="$0"

else 

  curfile="$PWD/${0#./}"

fi

#得到curfile 爲/usr/local/shell/automation/autoupdate_host.sh

php_path=`dirname $curfile`

#得到php_path爲/usr/local/shell/automation

PHP="/usr/local/php/bin/php -q "

PROGRAM="${php_path}/clear_his.php"

#echo $PHP $PROGRAM &

$PHP $PROGRAM &

====================== [和[[有什麼不同



$ type [
[ is a shell builtin
$ type [[
[[ is a shell keyword

也就是說[處理裏面的字串是當作參數來處理的,而[[對待其中的字串是當作表達式來處理的
那麼當作參數和表達式有什麼不同呢?

表達式中不會有wordsplitting 或者glob expansion,而參數處理會有

$ ls
file file 1 #注意是2個文件(file 和file 1)
$ (foo="file 1";[[ -f $foo ]]&&echo "$foo is a file")
file 1 is a file

]$ (foo="file 1";[ -f $foo ]&&echo "$foo is a file") # 這裏file 1被分成2個word,所以出錯
bash: [: file: binary operator expected

再來看看glob expansion

$ touch '*'
$ (foo="*";[ -f $foo ]&&echo "$foo is a file") #爲什麼顯示too many arguments,因爲 *被擴展爲所有目錄下的文件
bash: [: too many arguments
$ (foo="*";[[ -f $foo ]]&&echo "$foo is a file") # *被當成普通字符了
* is a file

參數傳遞中<和>會被解析成重定向符號,所以必須轉義掉

$ ([ "s" < "l" ]&&echo yes) #錯誤使用
bash: l: No such file or directory

$ ([ "s" \> "l" ] &&echo yes) #正確使用
yes

$ ([[ "s" > "l" ]] &&echo yes) #而在表達式中比較符號不會被當作重定向符號
yes

參數傳遞中小括號會被分割成token,而在表達式中則會被解析成運算順序

$ ([ "s" \> "l" -a ( file "l" \> "a" -o "l" \> "p" ) ]&&echo yes) #(和)必須被轉義,以避免參數解析中的不正確分詞
bash: syntax error near unexpected token `('

$ ([ "s" \> "l" -a \( "l" \> "a" -o "l" \> "p" \) ] &&echo yes)
yes

$ ([[ "s" > "l" && ( "l" > "a" || "l" > "p" ) ]] &&echo yes; ) #而表達式則不需要考慮這個
yes

================ shell判斷文件是否存在

shell判斷文件,目錄是否存在或者具有權限
#!/bin/sh

myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"


# 這裏的-x 參數判斷$myPath是否存在並且是否具有可執行權限
if [ ! -x "$myPath"]; then
mkdir "$myPath"
fi

# 這裏的-d 參數判斷$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi

# 這裏的-f參數判斷$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi

# 其他參數還有-n,-n是判斷一個變量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi

# 兩個變量判斷是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 not eq $var2'
fi

-f 和-e的區別
Conditional Logic on Files

-a file exists.
-b file exists and is a block special file.
-c file exists and is a character special file.
-d file exists and is a directory.
-e file exists (just the same as -a).
-f file exists and is a regular file.
-g file exists and has its setgid(2) bit set.
-G file exists and has the same group ID as this process.
-k file exists and has its sticky bit set.
-L file exists and is a symbolic link.
-n string length is not zero.
-o Named option is set on.
-O file exists and is owned by the user ID of this process.
-p file exists and is a first in, first out (FIFO) special file or named pipe.
-r file exists and is readable by the current process.
-s file exists and has a size greater than zero.
-S file exists and is a socket.
-t file descriptor number fildes is open and associated with aterminal device.
-u file exists and has its setuid(2) bit set.
-w file exists and is writable by the current process.
-x file exists and is executable by the current process.
-z string length is zero.

==================bash中的特殊符號

* 萬用字符,代表一個或多個字符(或數字)

? 萬用字符,代表一個字母

# 批註,這個最常被使用在 script 當中,視爲說明!

\ 跳脫符號,將『特殊字符或萬用字符』還原成一般字符

| 分隔兩個管線命令的界定;

; 連續性命令的界定(注意!與管線命令並不相同)

~ 使用者的家目錄

$ 亦即是變量之前需要加的變量取代值

& 將指令變成背景下工作

! 邏輯運算意義上的『非』 not 的意思!

/ 路徑分隔的符號

>, >> 輸出導向,分別是『取代』與『累加』

' 單引號,不具有變量置換的功能

" 具有變量置換的功能!

` ` 兩個『 ` 』中間爲可以先執行的指令!

( ) 在中間爲子 shell 的起始與結束

[ ] 在中間爲字符的組合

{ } 在中間爲命令區塊的組合!

exit 1:退出整個程序

--------------------dirname

dirname /home/bin/abc
得到/home/bin

------------------------- 循環讀取每行
all_corp=sql.txt
cat $all_corp | while read line
do
echo $line
done


-----------------------整數比較

-eq 等於,如:if [ "$a" -eq "$b" ]
-ne 不等於,如:if [ "$a" -ne "$b" ]
-gt 大於,如:if [ "$a" -gt "$b" ]

-ge 大於等於,如:if [ "$a" -ge "$b" ]
-lt 小於,如:if [ "$a" -lt "$b" ]
-le 小於等於,如:if [ "$a" -le "$b" ]

if [ $counter -gt 1 ]; then

...

fi


< 小於(需要雙括號),如:(("$a" < "$b"))
<= 小於等於(需要雙括號),如:(("$a" <= "$b"))
> 大於(需要雙括號),如:(("$a" > "$b"))
>= 大於等於(需要雙括號),如:(("$a" >= "$b"))

---------------------------字符串比較
= 等於,如:if [ "$a" = "$b" ]
== 等於,如:if [ "$a" == "$b" ],與=等價
注意:==的功能在[[]]和[]中的行爲是不同的,如下:
1 [[ $a == z* ]] # 如果$a以"z"開頭(模式匹配 )那麼將爲true
2 [ $a == "z*" ] # 如果$a等於z*(字符匹配 ),那麼結果爲true

3
4 [ $a == z* ] # File globbing 和word splitting將會發生
5 [ "$a" == "z*" ] # 如果$a等於z*(字符匹配),那麼結果爲true
一點解釋,關於File globbing是一種關於文件的速記法,比如"*.c"就是,再如~也是.
但是file globbing並不是嚴格的正則表達式,雖然絕大多數情況下結構比較像.
!= 不等於,如:if [ "$a" != "$b" ]
這個操作符將在[[]]結構中使用模式匹配.
< 小於,在ASCII字母順序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意:在[]結構中"<"需要被轉義.

> 大於,在ASCII字母順序下.如:
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意:在[]結構中">"需要被轉義.
具體參考Example 26-11來查看這個操作符應用的例子.
-z 字符串爲"null".就是長度爲0.
-n 字符串不爲"null"
注意:
使用-n在[]結構中測試必須要用""把變量引起來.使用一個未被""的字符串來使用! -z
或者就是未用""引用的字符串本身,放到[]結構中。雖然一般情況下可
以工作,但這是不安全的.習慣於使用""來測試字符串是一種好習慣.

awk \'{print $2}\' class.txt | grep \'^[0-9.]\' > res



iptables 配置文件目錄 /etc/sysconfig/iptables

1.別名 alias,存放位置 $HOME/.bashrc
alias ll=\'ls -lh\'
2.print=helloworld echo ${print}
3.變量:內存中一塊存儲單元
本地變量:登陸登出生命週期內有效,只限制於本用戶
變量名=變量值
set 查看
LOCAL="TEST"
echo $LOCAL
設置變量名爲只讀,不能在更改,同是也不能在恢復:readonly 變量名,不能刪除。

環境變量:系統變量,用於所有用戶,只有環境變量才能用於所有的子進程中,本地變量不可以。
存放於/etc/profile .bash_profile
export 變量名=變量值
env或者export查看
unset 變量名 刪除

變量替換:用變量的值替換變量的名
print=helloworld
echo ${print}
echo ${file1}+${file2}

--------------------位置變量:$0 $1...$9
$0:腳本的名字
$1:腳本的第一變量
$2:腳本的第二變量

向腳本中使用位置參數:./test.sh a b c

向系統命令傳遞參數
find /root/ -name $1 -print
./test.sh aa

標準變量:bash默認的,可以在/etc/profile中定義
EXINIT
HOME
IFS:設置分隔符,默認爲空格 IFS=":"SHE
LOGNAME
MAIL 默認郵箱位置
MAILPATH多個郵箱時可以設置
TERM 顯示終端類型
PS1 當前shell目錄格式PS1="WANGJIAN:"
ps2 >
pwd顯示當前路徑 SHELL 顯示當前shell
MANPATH TERMINFO


----------------------------------------------------------特殊變量
$# 變量的個數 $* 顯示腳本全部參數(參數列表)

$$腳本運行的當前id號
$?顯示前一個命令的運行狀態

$!後臺運行的最後一個進程id號
#!/bin/bash
echo "tesh.sh"
echo "this is first variable locate:$1"
echo "this is second variable locate:$2"
echo "this is third variable locate:$3"
shift
echo "count:$#"
echo "all list:$*"
echo "pid:$$"
echo "status:$?"

./tesh.sh a b c

declare :設置或顯示變量 -f只顯示函數名
export:創建環境變量 -p顯示所有環境變量
readonly:設置只讀變量,不能修改刪除
unset:取消變量的定義。-f 刪除只讀變量
shift:輸入的位置變量改變位置 shift 表位置上移一個位置,shift 2 表上移動兩個位置
雙引號"":引用字符或字符串除$ \ `
單引號\'\':直接引用爲字符或字符串
反引號``: 作爲系統命令執行 echo `echo wangjian` wangjian
反斜杆\:轉義特殊字符($*?)爲普通字符
運算符:~取反 << >>移位 &與(同1爲1,否0) |或(有1爲1,全0爲0) ^異或 邏輯運算符號&& ||
運用運算符:$[]:表示對其中的表達式求值 echo $[2+8] echo $[3&4] $[]等價於(())
[base#n] n(base>n)表示基數從2到36的任何基數 echo [10#8+1] 結果爲9
let a+=3 a=a+3
表達式優先級別[] *= || && | ^ & ==
shell 的輸入與輸出
echo
-e 解析轉義字符 echo -e "this is a bag \n\n\n"
-n 回車不換行,默認換行 echo -n "this is a cat"
轉義字符(\c回車不換行 \f禁止 \t跳格相當tab \n回車換行)

read:可以從鍵盤或文件的某一行文本中讀入信息,並將其賦給一個變量。
read varible1 varible2
如果只指定了一個變量,那麼read將會把所有的輸入賦給改變量,直至遇到文件結束或回車。如果多個變量,就依次賦給。shell用空格作爲變量之間的分隔符。
echo -n "first name:"
read firstname
echo -n "last name:"
read lastname
echo -e "your first name :${firstname}\n"
echo -e "your last name :${lastname}\n "

read -t 5 variable 5秒鐘超時
read -p "Please enter your Username: " user -p prompt 提示語
[root@ceshiji ~]#Please enter your Username:

read -s -p "Please enter your Password: " pass -s charaters are not echoed. 字符不回顯示。指輸入之後,不在回顯




cat:顯示文件內容,創建文件,還可以用它來顯示控制字符
cat file1 file2 file3 同時顯示
cat file1 file2 file3>myfile
cat -v dos.txt (-v 顯示控制符)

管道|:一個命令的輸出傳給一個命令的輸入
df -k|awk \'{print $1}\'|grep -v \'Filesystem\'

tee:把輸出的一個副本輸送到標準輸出,另一個副本拷貝到相應的文件中。
tee files 在看見輸出的同時,也將其存入一個文件。一般用於管道之後。
tee -a files 追加到files中 (-a 表追加)
who|tee who.out

標準輸入 0
標準輸出 1
標準錯誤 2

重定向:改變程序運行的輸入來源和輸出來源。
> >> < <<
command>>filename 2>&1
command <filename>filename2
cat file|sort 1 > sort.out 等價於cat file|sort > sort.out
pwd >> file.txt
>nullfile創建一個字節爲零的文件 >文件名

sort < file

cat >> aa.txt << CHINAITLAB 把CHINAITLAB結尾的內容都追加到aa.txt
>HELEO ,I AM WANGJIAN
>MY NAME IS $HOME
>bye ...
>CHINAITLAB

重定向標準錯誤:grep \'test\' file.txt 2>error.txt
grep "test" test.txt>error.txt 2>&1 有沒有錯誤都輸入到error.txt

exec用來替代當前的shell,並沒有啓動子shell,而是清楚現有shell環境,重新啓動一個shell
exec command
exec ./test.sh exec通常後接一個shell腳本

文件描述符
3-9可以使用 0輸入 1輸出 2錯誤
exec 3 <&0 0<name.txt 此時不會關閉當前的shell



控制流結構: if then eles case for until while break continue
if then
elif then
elif then
else
fi


if 條件1
then
語句
elif 條件2 (條件1不成立,執行條件2)
then
else (條件1 2都不成立,執行else)
語句
fi (結束)


if語句必須以單詞fi終止

if $x=sedsrc;then
echo
then
echo
fi

if [ "10" -lt "12" ]

man test

echo -n "enter your name:"
read NAME
if [ "$NAME" == ""];
then
echo "you did not enter any information"
else
echo "your name is $NAME"
fi

if cp myfile.bak myfile;
then
echo "GOOD COPY"
else
echo "basename $0 :error could not copy the files" >&2

case:多選擇語句。如果匹配成功,執行匹配的命令

case 值 in
模式1)
命令1
;;
模式2)
命令2
;;
esac
*表任意字符,?表任意單字符 []表範圍

echo -n "enter a number from 1 to 3;"
read ANS
case $ANS in
1)
echo "you select 1"
;;
2)
echo "you select 2"
;;
3)
echo "you select 3"
;;
*)
echo "basename $0 :this is not between 1 and 3" >&2
;;
esac


case $1 in
get|GET)
create_dir
get_config_file
;;
put|PUT)
put_config_file
;;
stop|STOP)
stop_server
;;
start|START)
start_server
;;
restart|RESTART)
restart_server
;;
*)
echo
echo "$Color_err Useage: ./Configure_squid.sh get|put|stop|start|restart $Color_end"
echo
exit 1
;;
esac



for
for 變量 in 列表
do
命令1
命令2
done
for語句 :提供循環執行
使用格式:
for var in values #var是變量 values是一組值
do
語句 #可以是多條語句
done
注意values的值可以全部列出,也可是通配的方式,也可以是某命令的輸出值(如$(ls))。
values的值可以是:
1.列表 in 1 2 3 4 5 用空格隔開
2.文件 in file1 file2 file3
3.變量 in $a 命令輸出賦值
4.命令 in `ls abc*`
5.字符串表 in "orange red blue gray"
5.特殊: 有時沒有in 此時將命令行參數傳入
for loop
do
find / -name $loop -print
done

[root@localhost ~]# ./sh match
/root/match
[root@localhost ~]# cat sh
#!/bin/bash
for loop
do
find /root -name $loop -print
done

#!/bin/sh
for ((i = 1; i < 254; i++)) #必須用兩個括號
do
arping -I eth0 60.191.82.$i -c 1
done
arp -a > mac_table


當變量值在列表裏,for循環即執行一次所有命令,使用變量名訪問列表中的取值。命令可爲任何有效的shell命令和語句。變量名爲任意單詞。in列表用法是可選的,如果不用它,for循環使用命令行的位置參數。in列表可以包含替換、字符串和文件名。
for((i=1;i<=10;i=i+1))
do
touch ar_$i;
touch full_$i;
done;

for i in {1..100}
do
.......
done

#!/bin/sh
for i in `seq 1 100`
do
echo $i
done

for loop in 1 2 3 4
do
echo $loop
done


for loop in "orange red blue grey"
do
echo $loop
done

for i in $(ls); do du -sh $i; done | sort -n 查看當前目錄的大小按小--大排列


until 條件
do
命令1
命令2
...
done
條件可爲任意測試條件,測試發生在循環末尾,因此循環至少執行一次.
read look
until [ "$look" ]
do
echo "full"
done

sleep 1
nohup ./test.sh &

while 命令
do
命令1
命令2
...
done

$ cat "filelist.txt"
name.txt□
txtf
□a□b□c□
$ while read file; do echo "$file"; done < "filelist.txt"
name.txt
txtf
a□b□c



echo "press ctrl+d ,stop"
while echo -n "enter a file for you like:" ; read film
do
echo " Yeah ,${file} is a good film "
done

while read line
do
echo $line
done<name.txt

break [n]:跳出循環,如果是在一個嵌入循環裏,可以指定n來跳出的循環個數
continue:跳過循環步驟(本次循環)

continue只能跳過本次循環。

while :<無限循環,需要加入break跳出>

while:
do
echo -n "enter any number [1...5]"
read ANS
case $ANS in
1|2|3|4|5)
echo "you enter a number between 1 and 5"
;;
*)
echo "wrong number ,bye."
break
;;
esac
done

shift n :參數向左偏移n位。
exit :退出系統
wc -l 查看文件的行數
getopts 多參數傳遞
ls -R 文件夾 遞歸查看
iostat 1
umount -a
sync:將緩衝區的內容寫到磁盤
r !date :讀入日期
r 文件 從文件中讀入
!pwd 執行命令 查看當前目錄
r !pwd 插入當前目錄
文本過濾
正則表達式:由一些字符要(元字符)組成,匹配字符串,過濾所需。
元字符:
^ :只匹配行首 $:只匹配行尾 *:匹配0個或多個此單字符
[]:只匹配[]內字符,可以是一個單字符,也可以是字符列表。可以使用-表示[]內字符序列範圍,入用[1-5]代替[12345]
\:只用來屏蔽一個元字符的特殊含義 . 只匹配任意單字符,如...x..x..x
pattern\{n\}:只用來匹配前面pattern出現次數,n爲次數
pattern\{n,\}:含義同上,但次數最少爲n
pattern\{n,m\}:含義同上,但pattern出現次數在n與m之間.
A\{2\}B:A出現兩次 AAB
A\{4,\}B:A最少出現4次,AAAAB AAAAAB
A\{2,4\}B: A出現次數範圍2-4次
[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}匹配ip地址
^:只允許在一行的開始匹配字符或單詞.
^d
drwxrwxrw- 匹配 -rwx--x--x 不匹配
^...1
3351xc 匹配 338xcd 不匹配
$:與^相反,只允許在行尾匹配字符或字符串
trouble$
^$ :匹配空行 ^.$:匹配包含一個字符的行
*:匹配任意字符包括零個字符 如300*2 3002 匹配
\:屏蔽一個特殊字符 如* $ .
\*\.pas:匹配以*.pas結尾的所有字符或文件.
[]:匹配一個範圍或集合 ,用逗號分開. 用-表示範圍
[0-9] [a-z] [A-Z a-z 0-9] [S,s]

find:用來查找具有某些特徵的文件的命令.遍歷大的文件系統時,一般放在後臺運行.

find path -options [-print -exec -ok]
-print 輸出到標準輸出
-exec 對匹配的文件執行該參數所給出的shell命令 形式爲 command {} \; 注意{}和\;之間有空格
find . -type f -exec ls -l {} \;
find . -name "*.log" -mtime +5 rm {} \;
有時參數太長或參數列溢出,此時要用xargs 類似與exec
find / -perm -7 -print |xargs chmod o-w
find / -type f -print |xargs file

-ok 和-exec作用相同,只不過-ok以一種更安全的方式運行.
-options:
-name文件名 文件名要引號
find ./ -name "aa.txt" -print
find ./ -name "[A-Z]*" -print 大寫開頭的
-perm文件權限
find -perm 755 -print (路徑沒有表示爲當前目錄)
-user文件的屬主
find `pwd` -user root -print
-group 文件的屬組

find ./ -group root -print
-atime ctime mtime -n +n -n 表示文件更改距現在n天以內(之內),+n表示文件更改時間距現在n天以前
find 、-mtime -5 -print 修改在5天內的文件
-size n[c] 查找文件長度爲n塊的文件,帶有c表示文件長度以字節計算
find . -size +1000000c -print 大於1000000c字節的文件
find . -size -100 小於100塊的文件
-type 類型 b p c f(普通文件)
-nouser -nogroup 無屬主,屬組的文件 ,刪除用戶時產生
find / -nouser -print
find / -newer "myfile" !-newer "yourfile" -print 查找比文件myfile新比yourfile舊的文件

-depth 在子目錄中查找
find . -name "aa.txt" -depth -print


grep 對文本文件進行模式查找
grep "jeny" *.txt
grep -c (只輸出匹配的行數)
grep -c "aa" aa.txt
grep -n (顯示匹配的行和行號)
grep -i (忽略大小寫)
grep -v (反向查找)
grep -h (查詢多文件時不顯示文件名)
grep -H (顯示文件名)
grep -s (不顯示不存在或無匹配文本的錯誤信息)
grep "2004:22:5[0-9]" aa.txt
grep "^[^210]" myfile 不顯示是210的行:包括2、1、0 打頭的行

grep "\?" aa.tet 查找?

grep "[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}" qshengyang12.xml 過濾除ip地址
grep "[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}" qshengzheng12.xml過濾mac地址

grep的命令類別

[[:upper:]] 等價於[A-Z]

[[:alnum:]] 等價於[0-9 a-z A-Z]
[[:lower:]] 等價於[a-z]
[[:space:]] 等價於空格或tab鍵
[[:digit:]] 等價於[0-9]
[[:alpha:]] 等價於[A-Z]

service dhcpd start > /dev/null 不顯示
grep "5[[:digit:]][[:digit:]]" file 在file中查找500 到599

nmap -sT ip地址
arping ip 地址

awk:是一種自解釋的編程語言,可從文件或字符串中基於指定規則瀏覽和抽取信息。
awk腳本由各種操作和模式組成
模式和動作
模式部分決定動作語句何時觸發及觸發事件。(BEGIN,END)
動作對數據進行處理,放在大括號{} 內指明。(print)
分隔符號、域和記錄
awk執行時,其瀏覽域標記爲$1,$2....$n。這種方法稱爲域標識。$0爲所有域。
注意執行時不要混淆符號$和shell提示符$,它們是不同的。
三種方式調用awk
命令方式:awk [-F filed-spearator] \'command\' input-files 用單引號 -F 來指定分隔符如 -F :
awk腳本:腳本文件
awk命令插入一個單獨文件: awk -f awk-script-file input-files
awk中的$跟shell中不含義不同 $0 是所有域,$1是第一個域 ,$2是第二個域....
awk \'{print $0}\' score.txt 按行打印文件score.txt的各行.即打印所有域。
awk -F : \'{print $0}\' score.txt默認分隔符是空格,可以用-F 來指定 本例子是:
awk \'{print $1 "\t" $3}\' score.txt 打印顯示第1和第3個域

awk \'BEGIN {print "num ip/n-----"} {print $1 "\t" $4} END {print "end-of-report"}\' ab.txt BEGIN和END定義了報頭 num ip 打印顯示第1和第4個域,最後顯示end-of-report
num ip
-----
64 172.0.0.1

函數定義:shell允許將一組命名集或語句形成一個可用塊,這些塊稱爲shell函數
格式:
函數名()
{
命令1
...
}

function 函數名()
{
....
}
定義函數
#!/bin/bash
function hello ()
{
echo "hello ,today is `date`"
return 1

}
echo "this is a function test"
hello

調用:直接輸入函數名
hello

參數傳遞到函數中
向函數傳遞參數就像在腳本中使用位置變量$1,$2,$3....$9
#!/bin/bash
function hello ()
{
echo "hello ,$1 today is `date`"
return 1
}
echo "this is a function test"
hello wangjian


顯示: hello ,wangjian says: today is Fri Oct 12 18:05:25 csT 2007

函數文件
文件1:
#!/bin/bash
.hellofun #調入函數hellofun
echo "now going to the function hello"
hello
echo "back from the function"

文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

>文件名:創建大小爲0的空文件

查看載入函數:set

文件1:
#!/bin/bash
.hellofun #調入函數hellofun
set
echo "now going to the function hello"
hello
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}
刪除函數:unset

文件1:
#!/bin/bash
.hellofun #調入函數hellofun
unset
echo "now going to the function hello"
hello
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

函數返回值:返回return的值 return 是何值就是何值。
文件1:
#!/bin/bash
.hellofun #調入函數hellofun
unset
echo "now going to the function hello"
hello
echo $?
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

awk深入學習
awk中特殊元字符 :+:表任意字符 ?:表單個字符
匹配操作符:~:匹配 !~:表示不匹配 使用:~/匹配內容/
cat score.txt|awk \'$0~/218.79.131.96/\'
awk \'$0 !~/218.79.131.96/\' score.txt
awk \'{if ($1=="218.79.131.96") print $0}\' score.txt
man awk
sed介紹
sed 選項 命令(\'\') 文件
sed不與初始化文件打交道,它操作的只是一個拷貝,然後所有的改動如果沒有重定向到一個爲文件,將輸出到屏幕。
sed是一種重要的文本過濾工具,使用一行命令或者使用管道與grep與awk相結合
非交互性文本流編輯。
調用sed有三種方式
使用sed命令行格式爲:sed [選項] sed命令 輸入文件命令用\'\'刮起來
使用sed 腳本文件,格式:sed [選項] -f sed 腳本文件 輸入文件
sed腳本文件 [選項] 輸入文件
不管是使用shell命令行方式或腳本文件方式,如果沒有指定輸入文件,sed從標準輸入中接受輸入,一般是鍵盤或重定向結果。
sed命令選項
n 不打印沒匹配的
c 下一命令是編輯命令
f 正在調用sed腳本文件
sed 在文件中查詢文本的方式
使用行號,可以是一個簡單數字,或者是一個行號範圍。
使用正則表達式
x 爲一行號
x,y 表示行號範圍從x到y
/pattern/ 查詢包含模式的行
/pattern/pattern/ 查詢包含兩個模式的行
pattern/,x 在給定的行號上查詢包含模式的行
x,/pattern/ 通過行號和模式查詢匹配行 (從x行匹配到/pattern結束)
x,y!查詢不包含指定行號x和y的行
基本sed編輯命令
p:打印匹配行
=:顯示文件行號
a\:在定位行號後附加新文本信息後面(分兩行寫)
i\:在定位行號後插入新文本信息前(分兩行寫)
d:刪除定位行
c\:用新文本替換定位文本
s:使用替換模式替換相應模式
r:從另一個文件中讀文件
w:寫文本到一個文件
q:第一個模式匹配完成後推出或立即推出
l:顯示與八進制ascii代碼等價的控制字符
{} 在定位行執行的命令組
n 從另一個文件中讀文本下一行,並附加在下一行
g 將模式2粘貼到/pattern n/
y 傳送字符
例子:
sed \'2p\' aa.txt 打印第2行(其他也打印)
sed -n \'2p\' aa.txt 只打印第二行
sed -n \'1,4p\' aa.txt 只顯示1-4行
sed -n \'/los/p\' aa.txt 只顯示 含有los的行
sed -n \'4,/los/p\' aa.txt 只顯示從第四行開始知道匹配到los爲止的之間所有行
sed -n \'/^$/=\' aa.txt 只顯示空行
sed -n -e \'/^$/p\' -e \'/^$/=\' aa.txt 只顯示空行和空行行號(-e 表示多命令同時執行)
sed -n \'/beijing/a\/shenzhen/\' aa.txt 在beijing所在行的下一行追加shenzhen(命令從/shenzhen/\' aa.txt換行(不改變aa)輸入)
sed -n \'/beijing/i\/shenzhen/\' aa.txt 在beijing所在行的前一行插入shenzhen(命令從/shenzhen/\' aa.txt換行輸入)不改變aa ,但可以重定到一個文件中改變原文件)
sed -n \'/beijing/c\/shenzhen/\' aa.txt 將beijing所在行替換shenzhen(命令從/shenzhen/\' aa.txt換行輸入)(不改變aa ,但可以重定到一個文件中改變原文件)


sed \'1,2d\' aa.txt 刪除1和2行
sed \'s/beijing/shanghai/g\' aa.txt
sed -n \'s/china/&hello/p\' aa.txt 在匹配到china字符後追加hello
sed -n \'s/china/hello &/p\' aa.txt在匹配到china字符前追加hello
sed \'1r bb.txt\' aa.txt 在aa.txt的第一行下面插入bb.txtwenjian
sed \'/china/q\' aa.txt 匹配到第一個china就退出
sed -n \'/china/l\' aa.txt 以八進制顯示
info sed man sed
sed \'/m/G\' 文件名搜索到回車加一個空行
awk \'/from/{print}\' 名打印所有含有from的行


-------------------------合併與分隔
sort 選項 files
許多不同的域按不同的列順序分類
-c 測試文件是否已經分類
-m合併兩個分類文件
-u刪除所有複製行
-o 存儲sort 結果的輸出文件名
-t 域分隔符;用非空格或tab鍵分隔域
+n n爲域號,使用此域號開始分類
n指定分類是域上的數字類項
-r 比較求逆
man sort

sort -c aa.txt
sort -u aa.txt 合併,有重複的行只顯示第一個
sort -r aa.txt 求逆,從下向上排序
sort -t "." +2 aa.txt 分隔符爲. 對第2個域進行ASCII碼排序 域號從0 1 2 ..
sort -t "." +2n aa.txt 分隔符爲. 對第2個域進行數字排序域號從0 1 2 ..

-----------------------uniq 選項 file
從一個文本文件中去除或禁止重複的行
-u 只先顯示不重複的行
-d 只顯示有重複的數據行,每種重複行只顯示一行
-c 打印每一重複行出現次數
-fn n爲數字,前n個域被忽略,只比較後面
man uniq

uniq -c file 查看重複次數(這裏重複指的是相鄰重複,隔行重複不算)
uniq -d file 只顯示有重複的數據行,每種重複行只顯示一行(相鄰重複,隔行重複不算)
uniq -f 2 myfile.txt 前2個域被忽略,從後面的域比較
uniq -d
sort aa.txt|uniq -c 等價於 sort -u aa.txt 查看重複次數(這裏重複指的是相鄰重複和隔行重複)
深入討論awk
條件操作符
~:匹配正則表達式
!~:不匹配正則表達式
&&:and
||:or
!:not
awk \'{if ($1~/^4/) print $0}\' file 如果文件file中第一個域匹配是4開頭的行就全部顯示
awk \'{if ($1!~/^4/) print $0}\' file 如果文件file中第一個域匹配不是4開頭的行就全部顯示
awk \'{if ($4~/^\[07\/jul\/2004/) print $0}\' file 打印是[07/jul/2004]開頭的所有行

--------------------------awk內置變量
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk 瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令-F選項。
NF 瀏覽文件域的個數
NR 已度的記錄數(行數)
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
文件aa的內容爲
ab#slfjslk
cd#fslkjf
df#123fjls
eb#j9sq
op#9sjtr
awk -F \'#\' \'{print NR,NF,$0}\' aa 打印行數 域數 所有記錄
awk -F \'#\' \'{print ENVIRON["USER"],FILENAME, $0 ARG ARGV[0]}\' aa 打印USER環境變量,文件名,所有記錄,參數個數,第一個參數。

--------------------------------字符串函數
gsub(r,s) 在整個$0中用s替代r
gsub(r,s,t)在整個t(域或記錄)中s替換r
index(s,t)返回s中字符串t的第一位置
length(s)返回s的長度
match(s,r)測試s中是否包含匹配r字符串
split(s,a,fs)用fs域上將s分成序列a
sprint(fmt,exp)返回經fmt格式化後的exp
sub(r,s) 用$0中最左邊最長的子串代替s
substr(s,p) 返回字符串s中從p開始的後部分
substr(s,p,n) 返回字符串s中從p開始長度爲n的後部分
awk -F \'#\' \'{if(gsub("s","S",$1)) print $1}\' aa.txt 替換文件aa.txt的$1中s變成S
awk -F \'#\' \'{if(gsub("s","S")) print $0}\' aa.txt 默認是$0
awk -F \'#\' \'{print(index($2,"s")) }\' aa.txt 打印$2中s字符所在的位置。(注意是字串在前)
awk 轉義字符
\b 退格鍵
\t tab鍵
\f 走紙換頁
\ddd 八進制值
\n 新行
\c 任意其他特殊字符,例如\\爲反斜線符號
\r 回車符
awk -F \'#\' \'{print(index($2,"s"),"\t" ,$2) }\' aa.txt


-------------------------------- printf修飾符
%c ASCII字符
%d 整數
%f 浮點數,例如(123.44)
%e 浮點數,科學記數法
%f 新行
%g awk 決定使用哪種浮點數轉換e或者f
%o 八進制數
%s 字符串
%x 十六進制數
awk 數組
awk \'BEGIN {print split ("as*123",array2,"*")}\'
./awk_arry.sh grade.txt
##############
# main menu()#
##############
curdate=`date "+%Y-%m-%d %T"`
date "+%Y-%m-%d %T"顯示當前日期和時間
case $a in
7)
exit
;;
*)
clear
continue
;;
esac

發佈了26 篇原創文章 · 獲贊 4 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章