1. 程式人生 > >馬哥教育二十七至三十天學習總結

馬哥教育二十七至三十天學習總結

函數、數組、變量

馬哥M28二十七、
進制轉換、
$(())可以將其他進制轉成十進制顯示出來,用法如下:
echo $((N#xxxxx)) N表示進制名稱如2 8 16;#後面跟的是當前進制數值
echo $((2#110)) -> 6

計劃任務crontab -e:
1.註意:crontab計劃任務中,最好的就是使用絕對路徑執行命令或者腳本,因為PATH定義不全
2.contab中 % 是有特殊含義的,必須使用\ 進行反轉義

1.參數相關的命令表示,$#表示命令行傳遞的參數個數;$或者$@表示打印所有傳遞的參數; $1,$2,$n 表示每個對應的參數; $@與$只有在使用雙引號""包含時才會有所不同,"$*"將所有參數作為一個整體字符串;而"$@"會將參數單獨輸出"$1" "$2"..

2.| xargs -n 1 userdel -r xargs本就是一個循環,使用-n 1將管道符傳遞的參數豎排顯示傳遞給後面的命令,將本能一次只能接收一個參數的命令可以循環接收多個參數
3.檢測所有用戶無論是通過終端tty還是su - 切換的方式都能過濾出來:ps aux,既是查看終端所有用戶的所有進程
4.排序: echo 1 -1 1.2 100 4 |xargs -n1 |sort -n
5.df |grep sda查看具體磁盤利用率
6.df |grep $diskname |while read lines;do
這種方式通過管道符將結果集傳給 while read lines;do .. done,這樣就可以不用生成文件再重定向獲取文件了
7.echo $RANDOM |md5sum |cut -c1-5 :學習md5sum對數字進行加密;因為md5加密方式是固定字符串了,所以可以循環逆向破解 $RANDOM 0~32767

#!/bin/bash
sum=0
for i in {1..32767};do
num=echo $i |md5sum | cut -c1-10
case $num in
efbaf275cd|4be9c40b8b|44b2395c46|f8c8873ce0|b902c16c8b|ad865d2f63)
echo $i
let sum++
;;
esac
if [ $sum -lt 6 ];then
continue
else

break
fi
done

練習:使用一條命令,一次創建指定的用戶,如執行createuser.sh tom bob alice harry
#!/bin/bash
while [ $# -gt 0 ]
do
id $1 &>/dev/null
if [ $? -eq 0 ];then
echo "$1 is already exsit."
shift
continue
fi
useradd $1
echo "$1 用戶創建成功"
shift
done

練習:每隔3秒鐘到系統上獲取已經登錄的用戶信息,如果發現用戶kacker登錄,則將登陸時間和主機記錄於日誌/var/log/login.log中,並退出腳本
#!/bin/bash
while true;do
if $(ps au |grep "^hacker." &>/dev/null);then
echo $(ps au |grep "^hacer.
" |tr -s " " |cut -d" " -f1,7,9 )>>/var/log/login.log
break
exit
else
sleep 3s
done

2.用兩個以上的數字為參數,顯示其中的最大值和最小值:
方法一:
#!/bin/bash
min=$1
max=$1
while [ $# -gt 0 ];do
value=$1
if [ $value -gt max ];then
max=value
elif [ $value -lt $min ];then
min=$value
fi
shift
done
echo "min is $min"
echo "max is $max"

練習:select in .. 配合case in ... esac
#!/bin/bash
PS3="Please choose your menu:"
select menu in a b c d
do
case in $REPLY in
a) echo "";;
b) echo "";;
...
done

練習:打印國際象棋(使用函數編寫腳本,每個格子由8個空格組成)
#!/bin/bash
red () {
echo -e "\033[41m \033[0m\c"
}
yel () {
echo -e "\033[43m \033[0m\c"
}
redyel () {
for ((i=;i<=4;i++));do
for ((j=1;j<=4;j++));do
[ "$1" = "-r" ] && { yel;red; } || { red;yel; }

                                            done
                                  echo 
                        done

}
for ((line=1;line<=8;line++));do
[ $[$line%2] -eq 0 ] && redyel || redyel -r
done

第二十九天、
函數.1.學習編程時調用系統shell好用的函數放到單獨的文件裏來實現某些功能調用存放函數的文件, . /path或者 source /path 使文件在當前shell環境中被讀取裏面的函數中的命令體並執行(調用函數時生效);
2.使用export聲明的變量是環境變量,可以被子shell使用
3.函數必須就是在當前shell環境下運行,使用腳本就是開啟一個子shell,函數在此下運行,又不會對腳本shell的shell產生影響;
4.ldd which 命令 查看命令所需要的所有類庫(查找並解決類庫丟失,使用cp不加任何參數復制時如果遇到軟連接等直接將所連接到源文件內容復制到新的鏈接文件中)
5.source /etc/init.d/functions 使其生效,有許多可以調用使用的函數,現成的學習範例,加以理解和學習使用
6.註意:推薦,在函數裏定義變量時,通常都需要使用Local或者set定義,Local定義局部變量只在函數體中生效,不影響外部shell以及外部函數;declare可以直接加變量名,但是不能單獨使用-g
7.平日裏,經常進行的操作或者功能都可以聯想到創建函數或者使用python程序實現,方便以後調用(功能模塊化

函數的返回值:
return var 可以將值儲存在變量中,return返回變量,也可以直接返回指定值,但不結束;
unset取消函數或者變量的定義(set var 定義變量),僅影響當前shell及其子shell.

練習:3.斐波那契數列--黃金分割數列,數列是:0,1,1,2,3,5,8,13,21.。。。 斐波那契數列以如下被遞歸的方法定義:F(0)=0,F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2) (n>=2)
利用函數,求n階斐波那契數列
#!/bin/bash
shulie () {
if [ $1 -eq 1 ];then
echo -n "0"
elif [ $1 -eq 2 ];then
echo -n "1"
elif [ $1 -gt 2 ];then
echo -n "$[$(shulie $[$1-1])+$[$(shulie $[$1-2])]"
fi

             }
     a=$1
                for i in $(seq 1 $a);do
                                    shulie  $i
                done
                echo 

漢諾塔(又稱河內塔)問題是源於印度一個古老傳說。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤,利用函數,實現N片盤的漢諾塔的移動步驟

#!/bin/bash
count=0
n_1()
{
let count++
echo "第${count}步:將${2}號圓盤從${1}移動到${3}"
}
n_2()
{
if [ $1 -eq 1 ];then
n_1 $2 1 $4
else
n_2 $[$1-1] $2 $4 $3
n_1 $2 $1 $4
n_2 $[$1-1] $3 $2 $4
}
read -p "please input the number: " num
n_2 $num X Y Z

num=3
n_2 3 X Y Z
n_2 2 X Z Y
fi
n_2 1 X Y Z
n_1 X 1 Z
輸出:第1步:將1由X移到Z
n_1 X 2 Y
輸出:第2步:將2由X移到Y
n_2 1 Z X Y
n_1 Z 1 Y
輸出:第3步:將1由Z移到Y
n_1 X 3 Z
輸出:第4步:將3由X移到Z
n_2 2 Y X Z
n_2 1 Y Z X
n_1 Y 1 X
輸出:第5步:將1由Y移動X

        n_1 Y 2 Z
            輸出:第6步:將2由Y移到Z

        n_2 1 X Y Z
            n_1 X 1 Z
                輸出:第7步:將1由X移到Z

第三十天、
數組:
declare -x varname :聲明環境變量
declare -xf 函數名 :聲明環境函數
declare -g :設置函數為全局函數
declare -a [數組名] 聲明索引數組或者查看所有索引數組
declare -A [數組名] 聲明關聯數組或者查看所有關聯數組

title[0]=boss;
name=(liubei guanyu zhanfei zhaoyun)
course=(/var/log/*.log) -->所有以.log結尾的文件保存到course數組中,支持通配;
b=([0]=linux [2]=python [5]=oracle) :稀疏索引數組,下標數值可以不連續;
read -a menu -->接收參數作為menu數組的元素存儲;

script=(/root/t*.sh)
digit=({1..20})

數組的引用
echo $digit :此為只引用digit數組的第一個值
echo ${digit[N]} 指定下標以引用索引數組對應下標的值;
echo ${digit[|@]} 引用數組的所有值
打印數組元素的數量
echo ${#array[
]} ${#..}

練習:分別顯示每一個值,每個值換行
1.for n in $(seq 0 $[${#array[*]}-1];do
echo array[$n] is ${array[$n]}
done
2.當下標默認是連續索引的索引數組
awk ‘{for (i in array).. } :在awk此類的語言中,循環遍歷數組的元素,此時i會循環遍歷array數組的索引,輸出$i只是打印遍歷的第一個索引對應的元素;
[root@magedu 2018-03-24 test_sh]# awk ‘BEGIN{split(‘"\"172.18.0.1\""‘,a,".");for(i in a)print i,a[i]}‘
4 1
1 172
2 18
3 0

3.在索引數組中加值,加到最後:
array[${#testshuzu[*]}]=machao;
刪除數組中的某個值:
unset array[i];
刪除整個數組:
unset array;

數組的切片:
    offset:要跳過的元素個數;
    number:要取出的元素個數;
    取偏移量之後的所有元素
    echo ${testshuzu[@]:1:3}  :跳過數組第一個元素,取之後的三個
    echo ${testshuzu[@]:1}   :跳過一個值,取到最後

關聯數組:
一、先聲明,再賦值
declare -A testshuzu
testshuzu=([zhugong]=liubei [erdi]=guanyu [sandi]=zhangfei)
二、聲明,賦值一步到位
declare -A weiguo=([chengxiang]=caocao ...)

    練習:寫一個腳本會生成一個名為digit的數組包含十個隨機數,顯示數組的所有值,再取最大值、最小值   ($RANDOM  0-32767)
       #!/bin/bash
         declare -i  min max
         declare -a digit
         for ((i=0;i<10;i++));do
                     digit[$i]=$RANDOM
                     [ $i -eq 0 ] && { min=${digit[0]};max=${digit[0]}; } && continue
                     [ ${digit[$i]} -gt $max ] && max=${digit[$i]} &&continue
                     [ ${digit[$i]} -lt $min ]  && min=${digit[$i]} &&continue
         done
         echo ALL digits are ${digit[*]}
         echo MAX is $max
         echo MIN  is $min

練習2.編寫腳本,定義一個數組,數組中的元素是/var/log目錄下的所有以.log結尾的文件,統計出其下標為偶數的文件中的行數之和
     #!/bin/bash
     sum=0
     declare  -a logfile=(/var/log/*.log)
     echo ALL logfiles name are ${logfile[*]}
     for i in $(seq 0 $[${#logfile[*]}-1]);do
               [ $[i%2] -eq 0 ] && let sum+=`cat ${logfile[$i]} |wc -l` ||continue
     done
     echo All lines are $sum

1.作業:輸入若幹數值存入數組中,采用冒泡算法進行升序或降序排序;
2.實現轉置矩陣matrix.sh
1 2 3 1 4 7
4 5 6 ==> 2 5 8
7 8 9 3 6 9

顯示變量或數組元素的字符數:
echo ${#var}     echo ${#array[N]}
echo ${name:2:3}   從變量name左邊跳過2個字符,取3個字符
echo ${name:2}   從變量name左邊跳過2個字符,取到最後
echo  ${name:  -2}   從變量name右側向左取兩個字符,註意冒號後至少打一個空格
echo ${name:  -3:1}  從右向左取3個字符,再從左向右去掉1個字符

echo ${name: -3: -1} 從右向左取3個字符,再從右向左去掉一個字符

字符串處理
從左向右查找:echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo ${PATH#local} : /sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
${var#
pattern} :從左向右匹配變量var的pattern並將左側第一個以及到最左側的字符串刪除

 echo ${PATH##*local}   :貪婪模式,將匹配到的最後一個local及其到最左側的字符串全部刪除顯示

從右至左
echo ${PATH%local*}   
echo ${PATH%%local*}
url=http://www.magedu.com:8080
echo ${url%%/*}  http:
echo ${url##*:}     8080

for i in /etc/profile.d/.sh ;do
if [ -r "$i" ];then
if [ "${-#
i}" != "$-" ];then : ‘-‘ 減號是一個變量,通過"$-"查看支持的擴展功能
. "$i"
else
. "$i" >/dev/null
fi
fi
done

查找替換:
${var/pattern/substr} :查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替換之;
${var//pattern/substr} :查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替換之;
${var/#pattern/substr} :查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替換之;
${var/%pattern/substr} :查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替換之;

查找並刪除:
${var/pattern} : 刪除所表示的字符串中第一次被pattern所匹配到的字符串
${var//pattern} : 刪除var所表示的字符串中所有被pattern所匹配到的字符串
${var/#pattern}: 刪除var所表示的字符串中所有以pattern為行首所匹配到字符串
${var/%pattern} : 刪除var所表示的字符串中所有以pattern為行尾所匹配到的字符串

大小寫轉換
name="Zhangfei Liubei"
echo ${name,,} 變量後面跟兩個逗號,表示大寫全部轉換成小寫
echo ${name^^} 變量後面跟兩個^^,表示小寫全部轉換成大寫

Shell變量一般是無類型的,但是bash Shell提供了declare和
typeset兩個命令用於指定變量的類型,兩個命令是等價的
? declare [選項] 變量名
-r 聲明或顯示只讀變量
-i 將變量定義為整型數
-a 將變量定義為數組
-A 將變量定義為關聯數組
-f 顯示已定義的所有函數名及其內容
-F 僅顯示已定義的所有函數名
-x 聲明或顯示環境變量和函數
-l 聲明變量為小寫字母 declare –l var=UPPER
-u 聲明變量為大寫字母 declare –u var=lower

[root@centos7 ~]# mage=linux
[root@centos7 ~]# linux=centos
[root@centos7 ~]# eval echo \$$mage
centos

[root@centos7 ~]# centos=redhat

[root@centos7 ~]# eval echo \$$(eval echo \$$mage)
redhat

[root@centos7 ~]# n=10
[root@centos7 ~]# echo {1..$n}
{1..10}
[root@centos7 ~]# eval echo {1..$n}
1 2 3 4 5 6 7 8 9 10

[root@centos7 ~]# echo $mage
linux
[root@centos7 ~]# echo $linux
centos
[root@centos7 ~]# test=${!mage}
[root@centos7 ~]# echo $test
centos

mktemp命令:創建並顯示臨時文件,可避免沖突
? mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出現三個
? OPTION:
-d: 創建臨時目錄
-p DIR或--tmpdir=DIR:指明臨時文件所存放目錄位置
? 示例:
mktemp /tmp/test.XXX
tmpdir=mktemp –d /tmp/testdir.XXX
mktemp --tmpdir=/testdir test.XXXXXX

ll命令:
install [OPTION]... [-T] SOURCE DEST 單文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...創建空目錄
? 選項:
-m MODE,默認755
-o OWNER
-g GROUP
? 示例:
install -m 700 -o wang -g admins srcfile desfile
install –m –d /testdir/installdir

install -m 700 -o liubei -g root /etc/passwd /app/hellopasswd

expect

ssh1.exp
#!/usr/bin/expect
spawn ssh [email protected]
expect {
"yes/no" { send "yes\n" ;exp_continue }
"password" { send "centos\n" }
}
interact
#expect eof

#!/usr/bin/expect
set user root
set remotehost 172.18.253.95
set password centos
spawn ssh $user@$remotehost
expect {
"yes/no" { send "yes\n" ;exp_continue }
"password" { send "$password\n" }
}
interact
#expect eof

執行登錄後的後續操作
#!/usr/bin/expect
set user [lindex $argv 0]
set remotehost [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$remotehost
expect {
"yes/no" { send "yes\n" ;exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd liubei\n" }
expect "]#" { send "echo redhat|passwd --stdin liubei\n" }
send "exit\n"
expect eof
~

使用shell腳本格式
#!/bin/bash
user=$1
remotehost=$2
password=$3
expect << EOF
spawn ssh $user@$remotehost
expect {
"yes/no" { send "yes\n" ;exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd liubei\n" }
expect "]#" { send "echo redhat|passwd --stdin liubei\n" }
send "exit\n"
expect eof
EOF

馬哥教育二十七至三十天學習總結