天天看點

Shell 程式設計進階(一)==條件判斷 if====條件判斷 case====循環==

文法格式:

逐條件進行判斷,第一次遇為“真”條件時,執行其分支,而後結束整個if語句

示例

判斷分數

适合判斷離散值,比如,1,3,9

可以有多種格式

case支援glob風格的通配符:

[ ] *: 任意長度任意字元

[ ] ?: 任意單個字元

[ ] []:指定範圍内的任意單個字元

[ ] a|b: a或b

練習

1、編寫腳本createuser.sh,實作如下功能:使

用一個使用者名做為參數,如果指定參數的使用者存在,就顯示其存在,否則添加之;顯示添加的使用者的id号等資訊

2、編寫腳本yesorno.sh,提示使用者輸入yes或no,

并判斷使用者輸入的是yes還是no,或是其它資訊

3、編寫腳本filetype.sh,判斷使用者輸入檔案路徑

顯示其檔案類型(普通檔案,目錄,連結,其它檔案類型)

[ -L $path] 是判斷:存在且為符号連結檔案,判斷的結果是以連結檔案背後的指向為準,也就是說,如果符号連結實際指向的一個目錄的話,這具判斷的結果就是一個目錄,而不是本身符号連結

是以上面的例子使用的是file來判斷。

比如這個檔案:

4、編寫腳本checkint.sh,判斷使用者輸入的參數是否為正整數

上面的例子用到了正規表達式,注意了 =~ 右邊不允許出現引号。echo -e 是啟用後面的顔色轉義。

循環執行

将某代碼段重複運作多次

重複運作多少次:

[ ] 循環次數事先已知

[ ] 循環次數事先未知

有進入條件和退出條件

第一種

[x] 執行機制:

依次将清單中的元素指派給“變量名” ; 每次指派後即執行一次循環體; 直到清單中的元素耗盡,循環結束。

清單生成方式:

[ ] (1) 直接給出清單

如:for i in 1 2 3

[ ] (2) 整數清單:

[ ] (a) {start..end}

如:for i in {a..z}

[ ] (b) $(seq [start [step]] end)

如:for i in $(seq 1 2 10)

[ ] (3) 傳回清單的指令$(COMMAND)

如:for i in $(seq 1 10)

[ ] (4) 使用通配符

如:for i in /app/shell/*.sh

[ ] (5) 變量引用;$@, $*

如:for i in $@

把1-100相加的結果顯示出來

文法格式:(第二種) C語言風格

運作結果

#!/bin/bash

for i in {1..100};do

if [ "$[i%3]" -ne 0 ];then

echo -n "$i "

let sum+=i

fi

done

echo -e "\n100以内不能被3整除的數相加的結果是:$sum"

1 2 4 5 7 8 10 11 13 14 16 17 19 20 22 23 25 26 28 29 31 32 34 35 37 38 40 41 43 44 46 47 49 50 52

53 55 56 58 59 61 62 64 65 67 68 70 71 73 74 76 77 79 80 82 83 85 86 88 89 91 92 94 95 97 98 100 

100以内不能被3整除的數相加的結果是:3367

_path=/var/*

for i in $_path;do

echo "$i的檔案類型是:<code>stat -c %F $i</code>"

#bash checkfile.sh 

/var/adm的檔案類型是:directory

/var/cache的檔案類型是:directory

/var/crash的檔案類型是:directory

/var/db的檔案類型是:directory

/var/empty的檔案類型是:directory

/var/games的檔案類型是:directory

/var/gopher的檔案類型是:directory

/var/kerberos的檔案類型是:directory

/var/lib的檔案類型是:directory

/var/local的檔案類型是:directory

/var/lock的檔案類型是:symbolic link

/var/log的檔案類型是:directory

/var/mail的檔案類型是:symbolic link

/var/nis的檔案類型是:directory

/var/opt的檔案類型是:directory

/var/preserve的檔案類型是:directory

/var/run的檔案類型是:symbolic link

/var/spool的檔案類型是:directory

/var/tmp的檔案類型是:directory

/var/www的檔案類型是:directory

/var/yp的檔案類型是:directory

stat -c 後面可以按指定格式輸出檔案屬性資訊

以下方法都可以取随機數,請參考:

#cat /dev/urandom |tr -dc 'a-zA-Z0-9'|head -c8

#openssl rand -base64 10|head -c8

#定義了記錄密碼檔案的變量

_passwdfile=/app/passwd.txt

for i in {1..10};do

#建立使用者并将建立的使用者名寫入指定檔案

useradd user$i

echo -n "user$i:" &gt;&gt; $_passwdfile

#算出随機數并交給passwd更新使用者密碼

echo "<code>openssl rand -base64 10|head -c8</code>" | tee -a $_passwdfile | passwd --stdin user$i &amp;&gt; /dev/null

echo "使用者user$i建立完畢,并設定了随機8位密碼,密碼記錄在:$_passwdfile"

#cat /app/passwd.txt 

user1:y70D9Jp7

user2:Ykseahss

user3:pSFLZ5bP

user4:9NNjOy4M

user5:LSiIB8IX

user6:0aGjxkWN

user7:pAvtRQkT

user8:GimQuuYN

user9:yR4YJR+U

user10:BxzFRlSW

tee指令用于将上一條指令的stdout重定向到檔案,并且重定向副本作為後續指令的stdin

-a:向檔案中重定向時使用追加模式,相當于重定向的 &gt;&gt;

#使用if的方法

_path=/etc/rc.d/rc3.d/

if [[ <code>basename $i</code> =~ ^K. ]];then

echo "$i stop"

elif [[ <code>basename $i</code> =~ ^S.* ]];then

echo "$i start"

#使用case的方法

case <code>basename $i</code> in

K)

echo "<code>basename $i</code> stop"

;;

S*)

echo "<code>basename $i</code> start"

esac

#bash checkrcd.sh 

/etc/rc.d/rc3.d/K50netconsole stop

/etc/rc.d/rc3.d/S10network start

#判斷使用者輸入的是否正整數

read -p "請輸入正整數num的值,腳本将會計算從1到num的總和并顯示: " num

if [[ ! $num =~ ^[1-9][0-9]*$ ]];then

echo "輸入的不是正整數,正整數的範圍是1-∞,腳本将會退出"

exit 10

else

unset sum

for i in <code>seq 1 "$num"</code>;do

let sum+=$i

echo "從1到num的總和 是:$sum"

#定義了IP位址中,網絡位址的格式,如 192.168.0

regex='\&lt;(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){2}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\&gt;'

#定義線上主機存放檔案

_onlineip=/app/online_ip.txt

#定義不線上主機存放檔案

_offlineip=/app/offline_ip.txt

#每次掃描前清空上次存放的記錄

$_onlineip $_offlineip read -p "請輸入要掃描的網絡位址,如 192.168.0 " ipnet #判斷輸入的網絡位址是否合法 if [[ ! "$ipnet" =~ $regex ]];then echo "輸入的網絡位址不合法,腳本将退出" for i in {1..254};do #這裡使用{ }是為了并行處理,提高效率 { if ping -c 2 -w 2 $ipnet.$i &amp;&gt; /dev/null;then echo "IP $ipnet.$i 線上" echo "$ipnet.$i" &gt;&gt; $_onlineip echo "IP $ipnet.$i 不線上" echo "$ipnet.$i" &gt;&gt; $_offlineip } &amp; wait

#bash scanip.sh 請輸入要掃描的網絡位址,如 192.168.0 192.168.4 IP 192.168.4.1 線上 IP 192.168.4.100 線上 IP 192.168.4.101 線上 IP 192.168.4.53 不線上 IP 192.168.4.31 不線上 IP 192.168.4.128 不線上 如果不用并發處理,看到的順序會從1~254,不過就太慢了。 wait指令可以讓背景執行程式執行完成後退出

_line=4

_colum=8

for i in <code>seq $_line</code>;do

for j in <code>seq $_colum</code>;do

echo -n "*"

echo

#bash juxing.sh

文法1:

#/bin/bash

#循環行數

for i in {1..9};do

#循環列的數量,等于行數

for j in <code>seq $i</code>;do

echo -ne "$j X $i = $[j*i]\t"

#輸出一個新行,便于每一行之後換行

#bash 99.sh 

1 X 1 = 1 

1 X 2 = 2 2 X 2 = 4 

1 X 3 = 3 2 X 3 = 6 3 X 3 = 9 

1 X 4 = 4 2 X 4 = 8 3 X 4 = 12 4 X 4 = 16 

1 X 5 = 5 2 X 5 = 10 3 X 5 = 15 4 X 5 = 20 5 X 5 = 25 

1 X 6 = 6 2 X 6 = 12 3 X 6 = 18 4 X 6 = 24 5 X 6 = 30 6 X 6 = 36 

1 X 7 = 7 2 X 7 = 14 3 X 7 = 21 4 X 7 = 28 5 X 7 = 35 6 X 7 = 42 7 X 7 = 49 

1 X 8 = 8 2 X 8 = 16 3 X 8 = 24 4 X 8 = 32 5 X 8 = 40 6 X 8 = 48 7 X 8 = 56 8 X 8 = 64 

1 X 9 = 9 2 X 9 = 18 3 X 9 = 27 4 X 9 = 36 5 X 9 = 45 6 X 9 = 54 7 X 9 = 63 8 X 9 = 72 9 X 9 = 81

文法2:

for (( i=1;i&lt;=9;i++ ));do

for (( j=1;j&lt;=i;j++ ));do

echo -ne "${j}x${i}=$[j*i]\t"

#bash 99-new.sh 

1x1=1 

1x2=2 2x2=4 

1x3=3 2x3=6 3x3=9 

1x4=4 2x4=8 3x4=12 4x4=16 

1x5=5 2x5=10 3x5=15 4x5=20 5x5=25 

1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36 

1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49 

1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64 

1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81

echo " 建立了 <code>mktemp --suffix=.html -p /tmp/ ${i}XXXXXXXX</code>"

#ls /tmp/

1tKMzfFfVx.html 2GvLrwZHn.html 4ms1ildS9.html 6ZwlWhu02.html 8k49voEHW.html

10FJDRpge.html 3khkjI5vu.html 5uOIumnYP.html 7pYy7KHuN.html 9QDJaNxg2.html

mktemp用于生成指定數量的随機臨時檔案。XXX是指定具體數量的随機符号,3個XXX就是3個,

--suffix=.html,用于指定字尾。

-p 用于指定目錄

#使用openssl rand 生成随機數方法

touch /tmp/$i<code>openssl rand -base64 12|tr -dc '[:alnum:]'|head -c8</code>.html

#使用cat /dev/urandom生成随機數方法

touch /tmp/$i<code>cat /dev/urandom|tr -dc '[:alnum:]'|head -c8</code>.html

至于效率哪個高,請使用time 腳本進行測試吧,工作中按需使用。

要點:

先打空格,再打星星

每行列印的空格數=總行數-目前行數

每行列印的星星數=目前行數 X 2 -1

read -p "請輸入總的行數:" topline

if [[ ! "$topline" =~ ^[1-9][0-9]$ ]];then

echo "你輸入的不是正整數"

#循環總數

for i in <code>seq $topline</code>;do

#每行列印的空格數=總行數-目前行數

for j in <code>seq $[$topline-$i]</code>;do

echo -n " "

#每行列印的星星數=目前行數x2-1 

for k in `seq $[$i2-1]`;do

#列印換行,進行下一輪循環

#bash sanjiao.sh

請輸入總的行數:5

*

#定義外層星星顔色

_color1="\033[1;5;$[$RANDOM%7+31]m"

_color2="\033[0m"

#定義内層星星顔色

_colorstar1="\033[1;$[$RANDOM%6+31]m*\033[0m"

if [[ ! "$topline" =~ ^[1-9][0-9]*$ ]];then

#列印數字1的邊

if [ "$i" -ne 1 ];then

echo -en "${_color1}1$_color2"

echo -e "${_color1}3$_color2"

#bash colorsanjiao.sh

請輸入總的行數:12

3

1*3

1***3

12222222222222222222223

唉,這微網誌的編輯器讓我原來的排版不美觀了。希望不影響各位

#b.sh

#定義顔色開關

_cr1="\033[1;"

_cr2="m \033[0m"

####################################################

num=4

for i in <code>seq $num</code>;do

#列印列顔色方格

for j in <code>seq $num</code>;do

echo -e "${_cr1}43${_cr2}\c"

echo -e "${_cr1}44${_cr2}\c"

#列印行顔色方格

for k in <code>seq $num</code>;do

a.sh

line=8

line2=$[line*2]

for i in <code>seq 1 8</code> ; do

for j in <code>seq 1 $line2</code> ; do

if [ $[i%2] -eq 1 ] ; then

if [ $[j%4] -eq 1 -o $[j%4] -eq 2 ] ; then

echo -ne "\033[41m \033[0m"

echo -ne "\033[42m \033[0m"

real 0m2.928s

user 0m1.012s

sys 0m1.958s

b.sh

real 0m2.622s

user 0m0.688s

sys 0m1.973s

real 0m3.188s

user 0m1.132s

sys 0m2.070s

real 0m2.571s

user 0m0.669s

sys 0m1.947s

real 0m2.867s

user 0m0.956s

sys 0m1.961s

real 0m2.217s

user 0m0.544s

sys

最後一個可以自定義顔色和方格數的

截圖:

Shell 程式設計進階(一)==條件判斷 if====條件判斷 case====循環==

版權聲明:原創作品,如需轉載,請注明出處。否則将追究法律責任

本文轉自 ljpwinxp 51CTO部落格,原文連結:http://blog.51cto.com/191226139/2055595