筆記:linux-sed[馬哥linux]__linux
來源:互聯網
上載者:User
sed
練習:寫一個指令碼
判斷當前系統上是否有使用者的預設shell為bash;
如果有,就顯示有多少個這類使用者;否則,就顯示沒有這類使用者;
grep "bash$" /etc/passwd &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep "bash$" /etc/passwd &> /dev/null; then
提示:“引用”一個命令的執行結果,要使用命令引用;比如: RESAULTS=`wc -l /etc/passwd | cut -d: -f1`;
使用一個命令的執行狀態結果,要直接執行此命令,一定不能引用;比如: if id user1一句中的id命令就一定不能加引號;
如果想把一個命令的執行結果賦值給某變數,要使用命令引用,比如USERID=`id -u user1`;
如果想把一個命令的執行狀態結果儲存下來,並作為命令執行成功與否的判斷條件,則需要先執行此命令,而後引用其狀態結果,如
id -u user1
RETVAL=$?
此句絕對不可以寫為RETVAL=`id -u user1`;
練習:寫一個指令碼
判斷當前系統上是否有使用者的預設shell為bash;
如果有,就顯示其中一個的使用者名稱;否則,就顯示沒有這類使用者;
練習:寫一個指令碼
給定一個檔案,比如/etc/inittab
判斷這個檔案中是否有空白行;
如果有,則顯示其空白行數;否則,顯示沒有空白行。
#!/bin/bash
A=`grep '^$' /etc/inittab | wc -l`
if [ $A -gt 0 ]; then
echo "$A"
else
echo "meiyoukongbaihang"
fi
—— by 張帥
#!/bin/bash
FILE=/etc/inittab
if [ ! -e $FILE ]; then
echo "No $FILE."
exit 8
fi
if grep "^$" $FILE &> /dev/null; then
echo "Total blank lines: `grep "^$" $FILE | wc -l`."
else
echo "No blank line."
fi
練習:寫一個指令碼
給定一個使用者,判斷其UID與GID是否一樣
如果一樣,就顯示此使用者為“good guy”;否則,就顯示此使用者為“bad guy”。
#!/bin/bash
USERNAME=user1
USERID=`id -u $USERNAME`
GROUPID=`id -g $USERNAME`
if [ $USERID -eq $GROUPID ]; then
echo "Good guy."
else
echo "Bad guy."
fi
進一步要求:不使用id命令獲得其id號;
#!/bin/bash
#
USERNAME=user1
if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then
echo "No such user: $USERNAME."
exit 1
fi
USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then
echo "Good guy."
else
echo "Bad guy."
fi
練習:寫一個指令碼
給定一個使用者,擷取其密碼警告期限;
而後判斷使用者密碼使用到期日是否已經小於警告期限;
提示:計算方法,最長使用到期日減去已經使用的天數即為剩餘使用到期日;
如果小於,則顯示“Warning”;否則,就顯示“OK”。
圓整:丟棄小數點後的所有內容
#!/bin/bash
W=`grep "student" /etc/shadow | cut -d: -f6`
S=`date +%s`
T=`expr $S/86400`
L=`grep "^student" /etc/shadow | cut -d: -f5`
N=`grep "^student" /etc/shadow | cut -d: -f3`
SY=$[$L-$[$T-$N]]
if [ $SY -lt $W ]; then
echo 'Warning'
else
echo 'OK'
fi
—— by 董利東
練習:寫一個指令碼
判定命令曆史中曆史命令的總條目是否大於1000;如果大於,則顯示“Some command will gone.”;否則顯示“OK”。
shell中如何進行算術運算:
A=3
B=6
1、let 算術運算運算式
let C=$A+$B
2、$[算術運算運算式]
C=$[$A+$B]
3、$((算術運算運算式))
C=$(($A+$B))
4、expr 算術運算運算式,運算式中各運算元及運算子之間要有空格,而且要使用命令引用
C=`expr $A + $B`
條件判斷,控制結構:
單分支if語句
if 判斷條件; then
statement1
statement2
...
fi
雙分支的if語句:
if 判斷條件; then
statement1
statement2
...
else
statement3
statement4
...
fi
多分支的if語句:
if 判斷條件1; then
statement1
...
elif 判斷條件2; then
statement2
...
elif 判斷條件3; then
statement3
...
else
statement4
...
fi
測試方法:
[ expression ]
[[ expression ]]
test expression
bash中常用的條件測試有三種:
整數測試:
-gt
-le
-ne
-eq
-ge
-lt
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2
檔案測試:
-e FILE:測試檔案是否存在
-f FILE: 測試檔案是否為普通檔案
-d FILE: 測試指定路徑是否為目錄
-r FILE: 測試目前使用者對指定檔案是否有讀取許可權;
-w
-x
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
練習:寫一個指令碼
給定一個檔案:
如果是一個普通檔案,就顯示之;
如果是一個目錄,亦顯示之;
否則,此為無法識別之檔案;
定義指令碼退出狀態代碼
exit: 退出指令碼
exit #
如果指令碼沒有明確定義退出狀態代碼,那麼,最後執行的一條命令的退出碼即為指令碼的退出狀態代碼;
測試指令碼是否有語法錯誤:
bash -n 指令碼
bash -x 指令碼:逐步執行
bash變數的類型:
本地變數(局部變數)
環境變數
位置變數:
$1, $2, ...
shift
特殊變數:
$?
$#:參數的個數
$*: 參數列表
$@:參數列表
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
練習:寫一指令碼
能接受一個參數(檔案路徑)
判定:此參數如果是一個存在的檔案,就顯示“OK.”;否則就顯示"No such file."
練習:寫一個指令碼
給指令碼傳遞兩個參數(整數);
顯示此兩者之和,之乘積;
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo "Usage: cacl.sh ARG1 ARG2"
exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]."
練習:寫一個指令碼,完成以下任務
1、使用一個變數儲存一個使用者名稱;
2、刪除此變數中的使用者,且一併刪除其家目錄;
3、顯示“使用者刪除完成”類的資訊;
bash:
引用變數:${VARNAME}, 括弧有時可省略。
整型,8bit: 256
0-255, 溢出
變數:
1,10000
10:16bit
10: 1010, 8bit
編程能力:
指令碼編程
grep, sed(流編輯器), awk
sed基本用法:
sed: Stream EDitor
行編輯器 (全屏編輯器: vi)
sed: 模式空間
預設不編輯原檔案,僅對模式空間中的資料做處理;而後,處理結束後,將模式空間列印至螢幕;
sed [options] 'AddressCommand' file ...
-n: 靜默模式,不再預設顯示模式空間中的內容
-i: 直接修改原檔案
-e SCRIPT -e SCRIPT:可以同時執行多個指令碼
-f /PATH/TO/SED_SCRIPT
sed -f /path/to/scripts file
-r: 表示使用擴充Regex
Address:
1、StartLine,EndLine
比如1,100
$:最後一行
2、/RegExp/
/^root/
3、/pattern1/,/pattern2/
第一次被pattern1匹配到的行開始,至第一次被pattern2匹配到的行結束,這中間的所有行
4、LineNumber
指定的行
5、StartLine, +N
從startLine開始,向後的N行;
Command:
d: 刪除合格行;
p: 顯示合格行;
a \string: 在指定的行後面追加新行,內容為string
\n:可以用於換行
i \string: 在指定的行前面添加新行,內容為string
r FILE: 將指定的檔案的內容添加至合格行處
w FILE: 將地址指定的範圍內的行另存至指定的檔案中;
s/pattern/string/修飾符: 尋找並替換,預設只替換每行中第一次被模式比對到的字串
加修飾符
g: 全域替換
i: 忽略字元大小寫
s///: s###, s@@@
\(\), \1, \2
l..e: like-->liker
love-->lover
like-->Like
love-->Love
&: 參考模式匹配整個串
sed練習:
1、刪除/etc/grub.conf檔案中行首的空白符;
sed -r 's@^[[:spapce:]]+@@g' /etc/grub.conf
2、替換/etc/inittab檔案中"id:3:initdefault:"一行中的數字為5;
sed 's@\(id:\)[0-9]\(:initdefault:\)@\15\ 2@g' /etc/inittab
3、刪除/etc/inittab檔案中的空白行;
sed '/^$/d' /etc/inittab
4、刪除/etc/inittab檔案中開頭的#號;
sed 's@^#@@g' /etc/inittab
5、刪除某檔案中開頭的#號及後面的空白字元,但要求#號後面必須有空白字元;
sed -r 's@^#[[:space:]]+@@g' /etc/inittab
6、刪除某檔案中以空白字元後面跟#類的行中的開頭的空白字元及#
sed -r 's@^[[:space:]]+#@@g' /etc/inittab
7、取出一個檔案路徑的目錄名稱;
echo "/etc/rc.d/" | sed -r 's@^(/.*/)[^/]+/?@\ 1@g'
基名:
echo "/etc/rc.d/" | sed -r 's@^/.*/([^/]+)/?@\ 1@g'
#abc
# hello world
# hi world
練習:
傳遞一個使用者名稱參數給指令碼,判斷此使用者的使用者名稱跟其基本組的組名是否一致,並將結果顯示出來。
字元測試:
==:測試是否相等,相等為真,不等為假
!=: 測試是否不等,不等為真,等為假
>
<
-n string: 測試指定字串是否為空白,空則真,不空則假
-z string: 測試指定字串是否不空,不空為真,空則為假
練習:寫一個指令碼
傳遞一個參數(單字元就行)給指令碼,如參數為q,就退出指令碼;否則,就顯示使用者的參數;
練習:寫一個指令碼
傳遞一個參數(單字元就行)給指令碼,如參數為q、Q、quit或Quit,就退出指令碼;否則,就顯示使用者的參數;
#!/bin/bash
#
if [ $1 = 'q' ];then
echo "Quiting..."
exit 1
elif [ $1 = 'Q' ];then
echo "Quiting..."
exit 2
elif [ $1 = 'quit' ];then
echo "Quiting..."
exit 3
elif [ $1 = 'Quit' ];then
echo "Quiting..."
exit 4
else
echo $1
fi
練習:
傳遞三個參數給指令碼,第一個為整數,第二個為算術運算子,第三個為整數,將計算結果顯示出來,要求保留兩位精度。形如:
./calc.sh 5 / 2
練習:
傳遞3個參數給指令碼,參數均為使用者名稱。將此些使用者的帳號資訊提取出來後放置於/tmp/testusers.txt檔案中,並要求每一行行首有行號。
寫一個指令碼:
判斷當前主機的CPU生產商,其資訊在/proc/cpuinfo檔案中vendor id一行中。
如果其生產商為AuthenticAMD,就顯示其為AMD公司;
如果其生產商為GenuineIntel,就顯示其為Intel公司;
否則,就說其為非主流公司;
寫一個指令碼:
給指令碼傳遞三個整數,判斷其中的最大數和最小數,並顯示出來。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
迴圈:進入條件,允出準則
for
while
until
for 變數 in 列表; do
迴圈體
done
for I in 1 2 3 4 5 6 7 8 9 10; do
加法運算
done
遍曆完成之後,退出;
如何產生列表:
{1..100}
`seq [起始數 [步進長度]] 結束數`
1,...,100
declare -i SUM=0
integer
-x
寫一個指令碼:
1、設定變數FILE的值為/etc/passwd
2、依次向/etc/passwd中的每個使用者問好,並顯示對方的shell,形如:
Hello, root, your shell: /bin/bash
3、統計一共有多少個使用者
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向預設shell為bash的使用者問聲好
寫一個指令碼:
1、添加10個使用者user1到user10,密碼同使用者名稱;但要求只有使用者不存在的情況下才能添加;
擴充:
接受一個參數:
add: 添加使用者user1..user10
del: 刪除使用者user1..user10
其它:退出
adminusers user1,user2,user3,hello,hi
寫一個指令碼:
計算100以內所有能被3整除的正整數的和;
模數,取餘:%
3%2=1
100%55=45
寫一個指令碼:
計算100以內所有奇數的和以及所有偶數的和;分別顯示之;
let I=$[$I+1]
SUM=$[$SUM+$I]
let SUM+=$I
let I+=1 相當於 let I++
-=
let I-=1 相當於 let I--
++I, --I
*=
/=
%=
寫一個指令碼,分別顯示當前系統上所有預設shell為bash的使用者和預設shell為/sbin/nologin的使用者,並統計各類shell下的使用者總數。顯示結果形如
:
BASH,3users,they are:
root,redhat,gentoo