a=$( expr 'helloworld20140501.txt' : '.*\([0-9]\{8\}\).*' ) echo $a linux shell 中能夠將命令的結果賦值給變量,$(命令)這種格式將返回命令執行後的結果字符串 上面命令執行後,變量a的值是20140501 a=`echo 'helloworld20140501.txt'|sed 's/.*\([0-9]\{8\}\).*/\1/'` 這個命令做用也是同樣,變量a被賦值爲20140501
===========================================================================html
Linux Shell中寫循環時,經常要用到變量的自增,如今總結一下整型變量自增的方法。
我所知道的,bash中,目前有五種方法:
1. i=`expr $i + 1`;
2. let i+=1;
3. ((i++));
4. i=$[$i+1];
5. i=$(( $i + 1 ))
能夠實踐一下,簡單的實例以下:linux
#!/bin/bash i=0; while [ $i -lt 4 ]; do echo $i; i=`expr $i + 1`; # let i+=1; # ((i++)); # i=$[$i+1]; # i=$(( $i + 1 )) done |
另外,對於固定次數的循環,能夠經過seq命令來實現,就不須要變量的自增了;實例以下:正則表達式
#!/bin/bash for j in $(seq 1 5) do echo $j done |
================================================================================shell
在服務器上加了一個服務檢測機制,用到正則來匹配IP和捕獲分組。shell和其餘語言同樣也可使用正則分組捕獲,不過不能使用 $1或\1這樣的形式來捕獲分組,能夠經過數組${BASH_REMATCH}來得到,如${BASH_REMATCH[1]},${BASH_REMATCH[N]}apache
簡單的測試以下所示:ubuntu
1數組 2bash 3服務器 4app 5 6 7 8 9 10 11 |
#!/bin/bash ip="121.0.2.2" if [[ $ip =~ ^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$ ]];then echo "match" echo ${BASH_REMATCH[1]} echo ${BASH_REMATCH[2]} echo ${BASH_REMATCH[3]} echo ${BASH_REMATCH[4]} else echo "Not match" fi |
=================================================================================
The command basename
is often used to extract the real file name without the file type specific file extension:
1 2 |
|
Now sometimes you need it the other way around, you might want to have the file extension. There are of course hundreds of ways to do so, but I found this one appealing since it also shows how the commandawk works (which I should learn a bit better I think):
1 2 |
|
The 「-F」 marks the delimiter, 「$NF」 means the last field generated. Seems to be a pretty straightforward tool.
==========================================================================
awk中使用的shell命令,有2種方法:
一。使用system()
二。使用print cmd | 「/bin/bash」
http://www.gnu.org/software/gawk/manual/gawk.html#I_002fO-Functions
一。使用因此system()
awk程序中咱們可使用system() 函數去調用shell命令
如:awk 'BEGIN{system("echo abc")}' file
echo abc 就會作爲「命令行」,由shell來執行,因此咱們會獲得如下結果:
root@ubuntu:~# awk 'BEGIN{system("echo abc")}'
abc
root@ubuntu:~#
root@ubuntu:~# awk 'BEGIN{v1="echo";v2="abc";system(v1" "v2)}'
abc
root@ubuntu:~#
root@ubuntu:~# awk 'BEGIN{v1="echo";v2="abc";system(v1 v2)}'
/bin/sh: echoabc: command not found
root@ubuntu:~#
root@ubuntu:~# awk 'BEGIN{v1=echo;v2=abc;system(v1" "v2)}'
root@ubuntu:~#
從上面的例子,咱們簡單的分析一下awk是怎樣調用system的:
若是system()括號裏面的參數沒有加上雙引號的話,awk認爲它是一個變量,它會從awk的變量裏面把它們先置換爲常量,而後再回傳給shell
若是system()括號裏面的參數有加上雙引號的話,那麼awk就直接把引號裏面的內容回傳給shell,做爲shell的「命令行」
二。使用print cmd | 「/bin/bash」
root@ubuntu:~# awk 'BEGIN{print "echo","abc"| "/bin/bash"}'
abc
root@ubuntu:~#
root@ubuntu:~# awk 'BEGIN{print "echo","abc",";","echo","123"| "/bin/bash"}'
abc
123
root@ubuntu:~#
三。總結
不管使用system()仍是print cmd | 「/bin/bash」
awk都是新開一個shell,在相應的cmdline參數送回給shell,因此要注意當前shell變量與新開shell變量問題
==========================================================================
獲取文件名和後綴名
代碼:
file=」thisfile.txt」
echo 「filename: ${file%.*}」
echo 「extension: ${file##*.}」
輸出:
filename: thisfile
extension: txt
附:
基於Pattern Matching的子串替換
${STR/$OLD/$NEW}
替換第一個。
${STR//$OLD/$NEW}
替換全部。
注意:不能使用正則表達式,只能使用?*的Shell擴展。只能用shell通配符如 * ? [list] [!list] [a-z]。
${STR/#$OLD/$NEW}
替換開頭。若是STR以OLD串開頭,則替換。
${STR/%$OLD/$NEW}
替換結尾。若是STR以OLD串結尾,則替換。
[user@laptop ~]# STR=」Hello World」
[user@laptop ~]# echo ${STR/o/O}
HellO World
[user@laptop ~]# echo ${STR//o/O}
HellO WOrld
[user@laptop ~]# STR=」Hello World」
[user@laptop ~]# echo ${STR/#He/he}
hello World
[user@laptop ~]# echo ${STR/#o/he}
Hello World
[user@laptop ~]# echo ${STR/%He/he}
Hello World
[user@laptop ~]# echo ${STR/%ld/lD}
Hello WorlD
若是被替換串包含/字符,那麼要轉義,寫成\/。
[user@laptop ~]# filename=」/user/admin/monitoring/process.sh」
[user@laptop ~]# echo ${filename/#\/user/\/tmp}
/tmp/admin/monitoring/process.sh
[user@laptop ~]# echo ${filename/%.*/.ksh}
/user/admin/monitoring/process.ksh
[user@laptop ~]#
將環境變量PATH的各個目錄分開,每行顯示一個。
echo -e ${PATH/:/\n}
[user@laptop ctmw]# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/apache/apache-ant-1.7.1/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/user/bin
[user@laptop ctmw]# echo -e ${PATH//:/’\n’}
/usr/kerberos/sbin
/usr/kerberos/bin
/usr/apache/apache-ant-1.7.1/bin
/usr/local/sbin
/usr/local/bin
/sbin
/bin
/usr/sbin
/usr/bin
/user/bin
[user@laptop ctmw]# echo 「${PATH//:/$’\n’}」
/usr/kerberos/sbin
/usr/kerberos/bin
/usr/apache/apache-ant-1.7.1/bin
/usr/local/sbin
/usr/local/bin
/sbin
/bin
/usr/sbin
/usr/bin
/user/bin
基於Pattern Matching的子串刪除
子串刪除是一種特殊的替換
${STR/$SUB}
將STR中第一個SUB子串刪除
${STR//$SUB}
將STR中全部SUB子串刪除
${STR#$PREFIX}
去頭,從開頭去除最短匹配前綴
${STR##$PREFIX}
去頭,從開頭去除最長匹配前綴
${STR%$SUFFIX}
去尾,從結尾去除最短匹配後綴
${STR%%$SUFFIX}
去尾,從結尾去除最長匹配後綴
注意:常常會記錯#和%的含義,有一個幫助記憶的方法
看一下鍵盤,#在$以前,%在$以後,就知道#去頭,%去尾。
注意:不能使用正則表達式,只能使用?*的Shell擴展。
[user@laptop ~]# STR=」Hello World」
[user@laptop ~]# echo ${STR#He}
llo World
[user@laptop ~]# echo ${STR#He*o}
World
[user@laptop ~]# echo ${STR##He*o}
rld
[user@laptop ~]# PREFIX=」*o」
[user@laptop ~]# echo ${STR#$PREFIX}
World
[user@laptop ~]# echo ${STR##$PREFIX}
rld
[user@laptop ~]# echo ${STR%o*}
Hello W
[user@laptop ~]# echo ${STR%%o*}
Hell
[user@laptop ~]# SUFFIX=」o*」
[user@laptop ~]# echo ${STR%$SUFFIX}
Hello W
[user@laptop ~]# echo ${STR%%$SUFFIX}
Hell
典型應用:獲得文件的擴展名
[user@laptop ~]# FILE=hello.jpg
[user@laptop ~]# echo ${FILE##*.}
jpg
使用sed命令實現正則表達式替換
使用sed命令能夠進行正則表達式的替換。
echo 「$STR」 | sed 「s/$OLD/$NEW/」
將STR中的OLD子串替換成NEW。
[user@laptop ~]# STR=」123456789″
[user@laptop ~]# echo 「$STR」 | sed s/345/OK/
12OK6789
[user@laptop ~]# OLD=345
[user@laptop ~]# NEW=OK
[user@laptop ~]# echo 「$STR」 | sed 「s/$OLD/$NEW/」
12OK6789
使用tr命令實現字符集合的替換
使用tr命令能夠實現字符的替換,而且能夠是從一批字符到另外一批字符的替換。好比小寫字母變成大寫字母,或者反過來。
[user@laptop ~]# echo 「bash」 | tr 「[a-z]」 「[b-z]」
cbti
上面的命令是將原串中的a替換成b,被替換成c,以此類推。
網上問題:Linux中 有沒有一個命令能夠將 字符串中出現的 +或者- 替換成對應的-或者+ 即 「+」 ——> 「-」 「-」——>」+」 例如 GMT+8-9變成 GMT-8+9
[user@laptop ~]# echo 「GMT+8-9″ | sed ‘s/-/#/g’ | sed ‘s/+/-/g’ | sed ‘s/#/+/g’
GMT-8+9
上面是網上提供的答案。若是用tr來實現,更簡潔些。
[user@laptop ~]# echo 「GMT+8-9″ | tr 「+-」 「-+」
GMT-8+9
路徑字符串的處理
dirname ${FULLPATH}
取目錄部分。
basename ${FULLPATH}
取文件名部分。
basename ${FULLPATH} ${EXT}
取文件名部分,而且去掉指定的擴展名。
[user@laptop ~]# FULLPATH=/user/work/project/backup.tar.gz
[user@laptop ~]# dirname 「$FULLPATH」
/user/work/project
[user@laptop ~]# basename 「$FULLPATH」
backup.tar.gz
[user@laptop ~]# basename 「$FULLPATH」 .gz
backup.tar
[user@laptop ~]# basename 「$FULLPATH」 .tar
backup.tar.gz
[user@laptop ~]# basename 「$FULLPATH」 .tar.gz
backup
取目錄部分:${FULLPATH%/*}
(相似 dirname 「$FULLPATH」)
取文件名稱:FILE=${FULLPATH##*/}
(相似 basename 「$FULLPATH」)
取最短基本名稱:${FILE%%.*}
取最長基本名稱:${FILE%.*}
取最短擴展名:${FILE##*.} 或者 ${FULLPATH##*.}
取最長擴展名:${FILE#*.} 或者 ${FULLPATH#*.}
[user@laptop ~]# FULLPATH=/user/work/project/backup.tar.gz
[user@laptop ~]# echo ${FULLPATH%/*}
/user/work/project
[user@laptop ~]# dirname 「$FULLPATH」
/user/work/project
[user@laptop ~]# FILE=${FULLPATH##*/}
[user@laptop ~]# echo $FILE
backup.tar.gz
[user@laptop ~]# basename 「$FULLPATH」
backup.tar.gz
[user@laptop ~]# echo ${FILE%%.*}
backup
[user@laptop ~]# echo ${FILE%.*}
backup.tar
[user@laptop ~]# echo ${FILE##*.}
gz
[user@laptop ~]# echo ${FILE#*.}
tar.gz
=============================================================================