shell腳本語法

  1. 使用CRT軟件登陸到linux虛擬機,使用pwd命令查看當前路徑爲/root目錄php

    shell腳本的執行方法
  2.  

    使用vi編輯器編寫第一個shell文件 hello.sh, 注意必定要以.sh結尾html

    shell腳本的執行方法
  3.  

    編寫第一個shell文件,#!/bin/bash 是必需要寫的,表示要是/bin/bash這個執行腳本的命令執行接下來寫的腳本, echo "hello world !!"表示想前端打印一句話前端

    shell腳本的執行方法
  4.  

    經過chmod命令賦予該腳本的執行權限chmod 755 hello.sh,不然沒有執行權限,/root/hello.sh表示在全路徑下執行該shell腳本linux

    shell腳本的執行方法
  5.  

    ./hello.sh 表示在當前路徑下執行該shell腳本ios

    shell腳本的執行方法
  6.  

     bash hello.sh這種方式執行腳本,hello.sh中就不須要指定#!/bin/bash這句話,由於你已經指定了bash這種執行腳本方式的命令,固然加了#!/bin/bash也不會有問題git

    shell腳本的執行方法
  7.  

    像ls這種命令也能夠算是一種腳本,可是咱們不須要添加路徑就能執行,是由於該命令添加進系統環境變量(環境變量詳解個人另外一篇經驗)正則表達式

    shell腳本的執行方法
    END

注意事項

  • shell腳本名要以.sh結尾

 

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

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

  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

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

 

一、字符串判斷

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

二、數字的判斷

  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)指定的設備爲終端時爲真

三、複雜邏輯判斷
  -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 至關於使用了FD一、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的行:包括二、一、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 in7)exit;;*)clearcontinue;;esac

相關文章
相關標籤/搜索