字符串截取及切割

1.字符串截取及切割
問題
使用Shell完成各種Linux運維任務時,一旦涉及到判斷、條件測試等相關操作時,往往需要對相關的命令輸出進行過濾,提取出符合要求的字符串。
本案例要求熟悉字符串的常見處理操作,完成以下任務練習:
參考PPT示範操作,完成子串截取、替換等操作
根據課上的批量改名腳本,編寫改進版renfilex.sh:能夠批量修改當前目錄下所有文件的擴展名,修改前/後的擴展名通過位置參數$1、$2提供
方案
子串截取的三種用法:
var::exprsubstr"{var:起始位置:長度} expr substr "var" 起始位置 長度
echo varcutbdirname""basename""var | cut -b 起始位置-結束位置 路徑分割: 取目錄位置:dirname "字符串" 取文檔的基本名稱:basename "字符串" 子串替換的兩種用法: 只替換第一個匹配結果:{var/old/new}
替換全部匹配結果:var//old/new{var//old/new} 字符串掐頭去尾: 從左向右,最短匹配刪除:{變量名#關鍵詞}
從左向右,最長匹配刪除:KaTeX parse error: Expected '}', got '#' at position 5: {變量名#̲#*關鍵詞} 從右向左,最短匹…{變量名%關鍵詞
}
從右向左,最長匹配刪除:${變量名%%關鍵詞*}
步驟
實現此案例需要按照如下步驟進行。
步驟一:字符串的截取
1)方法一,使用 {}表達式 格式:{var:起始位置:長度}
定義一個變量SCHOOL,並確認其字符串長度:
[root@svr5 ~]# SCHOOL=“Tarena IT Group.”
[root@svr5 ~]# echo KaTeX parse error: Expected '}', got '#' at position 2: {#̲SCHOOL} 16 …{}截取時,起始位置可以省略,省略時從第一個字符開始截。比如,以下操作都可以從左側開始截取前6個字符:
[root@svr5 ~]# echo ${SCHOOL::6}
Tarena
或者
[root@svr5 ~]# echo SCHOOL:0:6Tarena使{SCHOOL:0:6} Tarena 使用{}方式截取字符串時,起始位置是從0開始的(和數組下標編號類似) 。
因此,如果從起始位置1開始截取6個字符,那就變成這個樣子了:
[root@svr5 ~]# echo KaTeX parse error: Expected 'EOF', got '#' at position 117: …: [root@svr5 ~]#̲ md5sum /etc/fs…(md5sum /etc/fstab) //保存到變量
[root@svr5 ~]# echo MD5STR::32//32MD5eef0254e6049a411dc30db864c0ee6ea2使exprsubstrexprsubstr"{MD5STR::32} //截取前32個字符(MD5值的固定長度) eef0254e6049a411dc30db864c0ee6ea 2)方法二,使用 expr substr 格式:expr substr "var" 起始位置 長度
還以前面的SCHOOL變量爲例,確認原始值:
[root@svr5 ~]# echo $SCHOOL
Tarena IT Group.
[root@svr5 ~]# echo KaTeX parse error: Expected '}', got '#' at position 2: {#̲SCHOOL} 16 使用ex…{}相區分。
從左側截取SCHOOL變量的前6個字符:
[root@svr5 ~]# expr substr “$SCHOOL” 1 6
Tarena
這裏注意,因爲SCHOOL變量的值裏含有空格,所以應該加雙引號進行調用,否則是會報錯的:
[root@svr5 ~]# expr substr KaTeX parse error: Expected 'EOF', got '#' at position 61: …: [root@svr5 ~]#̲ expr substr "SCHOOL" 11 16
Group.
應用示例:還是提取文件/etc/fstab的MD5SUM校驗和字串,排除無關文本。若採用expr substr,則相關操作及結果如下所示:
[root@svr5 ~]# md5sum /etc/fstab //確認MD5SUM校驗值
eef0254e6049a411dc30db864c0ee6ea /etc/fstab
[root@svr5 ~]# MD5STR=KaTeX parse error: Expected 'EOF', got '#' at position 44: …量 [root@svr5 ~]#̲ expr substr "MD5STR" 1 32 //截取前32個字符
eef0254e6049a411dc30db864c0ee6ea
3)方式三,使用cut分割工具
格式:echo $var | cut -b 起始位置-結束位置
選項 -b 表示按字節截取字符,其中起始位置、結束位置都可以省略。當省略起始位置時,視爲從第1個字符開始(編號也是從1開始,與expr類似),當省略結束位置時,視爲截取到最後。
還以前面的SCHOOL變量爲例,確認原始值:
[root@svr5 ~]# echo $SCHOOL
Tarena IT Group.
[root@svr5 ~]# echo ${#SCHOOL}
16
從左側截取前6個字符,可執行以下操作:
[root@svr5 ~]# echo $SCHOOL | cut -b 1-6
Tarena
或者
[root@svr5 ~]# echo $SCHOOL | cut -b -6
Tarena
截取第11-16個字符:
[root@svr5 ~]# echo $SCHOOL | cut -b 11-16
Group.
從第8個字符截取到末尾:
[root@svr5 ~]# echo $SCHOOL | cut -b 8-
IT Group.
只截取單個字符,比如第9個字符:
[root@svr5 ~]# echo $SCHOOL | cut -b 9
T
如果起始位置、結束位置同時省略,那就和直接echo變量值沒啥區別了:
[root@svr5 ~]# echo KaTeX parse error: Expected 'EOF', got '#' at position 123: …: [root@svr5 ~]#̲ md5sum /etc/fs…{var/old/new}
以前面的SCHOOL變量作爲測試,先確認變量值:
[root@svr5 ~]# echo $SCHOOL
Tarena IT Group.
將字符串中的第1個r替換爲RRRR:
[root@svr5 ~]# echo SCHOOL/r/RRRRTaRRRRenaITGroup.2{SCHOOL/r/RRRR} TaRRRRena IT Group. 2)替換全部子串 格式:{var//old/new}
以前面的SCHOOL變量作爲測試,先確認變量值:
[root@svr5 ~]# echo $SCHOOL
Tarena IT Group.
將字符串中的所有r都替換爲RRRR:
[root@svr5 ~]# echo ${SCHOOL//r/RRRR}
TaRRRRena IT GRRRRoup.
3)應用示例,根據變量值重設主機名
用法分解,將當前主機名的域後綴替換爲“localdomain”:
[root@svr5 ~]# echo $HOSTNAME //確認當前的主機名
svr5.tarena.com
[root@svr5 ~]# echo ${HOSTNAME/tarena.com/localdomain}
svr5.localdomain //替換後的字串
將當前主機名整個替換爲“localhost.localdomain”:
[root@svr5 ~]# echo KaTeX parse error: Expected '}', got 'EOF' at end of input: {HOSTNAME/HOSTNAME/localhost.localdomain}
localhost.localdomain
假設要設置的新主機名保存在變量MYFQDN內,則重設操作如下所示:
[root@svr5 ~]# MYFQDN=“dbsvr.example.org” //新主機名變量
[root@svr5 ~]# hostname KaTeX parse error: Expected '}', got 'EOF' at end of input: {HOSTNAME/HOSTNAME/$MYFQDN} //重設操作
[root@svr5 ~]# hostname //確認修改後的主機名
dbsvr.example.org
如果希望恢復爲原來的主機名,只要修改變量MYFQDN的值,然後再重新執行一遍替換操作即可:
[root@svr5 ~]# MYFQDN=“svr5.tarena.com” //定義要恢復的主機名
[root@svr5 ~]# hostname KaTeX parse error: Expected '}', got 'EOF' at end of input: {HOSTNAME/HOSTNAME/$MYFQDN} //重設主機名
[root@svr5 ~]# hostname //確認恢復結果
svr5.tarena.com
引入變量來保存主機名以後,可以使Shell腳本具有更廣泛的適用性。
步驟三:字符串的匹配刪除
以處理系統默認的郵箱路徑爲例,可直接使用環境變量MAIL:
[root@svr5 ~]# echo MAIL/var/spool/mail/root1MAIL /var/spool/mail/root 1)從左向右,最短匹配刪除 格式:{變量名#關鍵詞}
刪除從左側第1個字符到最近的關鍵詞“oo”的部分,
作通配符理解:
[root@svr5 ~]# echo ${MAIL#oo}
l/mail/root
刪除從左側第1個字符到最近的關鍵詞“/”的部分:
[root@svr5 ~]# echo KaTeX parse error: Expected '}', got '#' at position 6: {MAIL#̲*/} var/spool/m…{變量名##關鍵詞}
刪除從左側第1個字符到最遠的關鍵詞“oo”的部分:
[root@svr5 ~]# echo $MAIL //確認變量MAIL的值
/var/spool/mail/root
[root@svr5 ~]# echo ${MAIL##oo}
t
刪除從左側第1個字符到最遠的關鍵詞“/”的部分:
[root@svr5 ~]# echo ${MAIL##
/}
root
操作 ${MAIL##
/} 的效果與使用basename命令提取基本名稱的效果相同:
[root@svr5 ~]# basename MAILroot3MAIL root 3)從右向左,最短匹配刪除 格式:{變量名%關鍵詞
}
刪除從右側最後1個字符到往左最近的關鍵詞“oo”的部分,* 做通配符理解:
[root@svr5 ~]# echo $MAIL //確認變量MAIL的值
[root@svr5 ~]# echo ${MAIL%oo*}
/var/spool/mail/r
刪除從右側最後1個字符到往左最近的關鍵詞“/”的部分:
[root@svr5 ~]# echo ${MAIL%/}
/var/spool/mail
操作 ${MAIL%/
} 的效果與使用dirname命令提取目錄名稱的效果相同:
[root@svr5 ~]# dirname MAIL/var/spool/mail4MAIL /var/spool/mail 4)從右向左,最長匹配刪除 格式:{變量名%%關鍵詞*}
刪除從右側最後1個字符到往左最遠的關鍵詞“oo”的部分:
[root@svr5 ~]# echo $MAIL //確認變量MAIL的值
/var/spool/mail/root
root@svr5 ~]# echo ${MAIL%%oo*}
/var/sp
刪除從右側最後1個字符到往左最遠的關鍵詞“/”的部分(刪沒了):
[root@svr5 ~]# echo ${MAIL%%/*}

[root@svr5 ~]#
步驟四:編寫renfilex.sh腳本
1)驗證原始改名腳本renfile.sh的效果
腳本用途爲:批量修改當前目錄下的文件擴展名,將.doc改爲.txt。
腳本內容參考如下:
[root@svr5 ~]# vim renfile.sh
#!/bin/bash
for FILE in *.doc
do
mv $FILE ${FILE%.doc}.txt
done
[root@svr5 ~]# chmod +x renfile.sh
創建一個測試用的文件夾rendir,並在其下建幾個測試文件
[root@svr5 ~]# mkdir rendir
[root@svr5 ~]# cd rendir
[root@svr5 rendir]# touch file1.doc abcde.doc xxyyzz.doc other1.xls killbill.mp4
[root@svr5 rendir]# ls
abcde.doc file1.doc killbill.mp4 other1.xls xxyyzz.doc
調用renfile.sh腳本,查看修改結果(原來擴展名爲.doc的文件,其擴展名都變成了.txt):
[root@svr5 rendir]# …/renfile.sh
[root@svr5 rendir]# ls
abcde.txt file1.txt killbill.mp4 other1.xls xxyyzz.txt
2)建立改進版腳本renfilex.sh
要適應不同擴展名文件的修改,並能夠反向還原。
修改前的擴展名、修改後的擴展名通過位置變量 $1、$2提供。
改進的腳本編寫參考如下:
[root@svr5 rendir]# cp …/renfile.sh …/renfilex.sh
[root@svr5 rendir]# vim …/renfilex.sh
#!/bin/bash
for FILE in “$1”
do
mv $FILE ${FILE%$1}"$2"
done
3)驗證、測試改進後的腳本
將 *.doc文件的擴展名改爲.txt:
[root@svr5 rendir]# ls //修改前
abcde.txt file1.txt killbill.mp4 other1.xls xxyyzz.txt
[root@svr5 rendir]# …/renfilex.sh .txt .doc
[root@svr5 rendir]# ls //修改後
abcde.doc file1.doc killbill.mp4 other1.xls xxyyzz.doc
將 *.mp4文件的擴展名改爲.mkv:
[root@svr5 rendir]# ls //修改前
abcde.doc file1.doc killbill.mp4 other1.xls xxyyzz.doc
[root@svr5 rendir]# …/renfilex.sh .mp4 .mkv
[root@svr5 rendir]# ls //修改後
abcde.doc file1.doc killbill.mkv other1.xls xxyyzz.doc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章