sed和awk的運用

1, 怎樣處理用戶名?(怎樣從/etc/passwd中把用戶目錄讀出來?)
引用 :
我在作一個自動設置輸入法環境變量的腳本,由於是用 root 運行,因此我就想從 /etc/passwd 裏把用戶目錄給讀出來。如今的狀況是這樣:
[tram@~]$ sed -n '{s/^[^\/]*//;s/\:.*//;p}' /etc/passwd
/root
/home/tram
/home/kde
[tram@~]$
算是獲得了每一個用戶的根目錄,可是要怎樣才能一個一個的設置呢?由於在運行前,是不知道有幾個用戶的,是否是能作一循環呢?謝謝!
解答參考 :
a,sed
代碼 :
sed -n '{s/^[^\/]*//;s/\:.*//;p}' /etc/passwd
b,awk
代碼 :
awk -F: '{print $6}' /etc/passws
c,cut
代碼 :
cut -f6 -d: /etc/passwd
d,script
代碼 :
#! /bin/bash
#showhome.sh
IFS=:
while read name pass uid gid gecos home shell
do
    echo $home
done
執行 ./showhome.sh < /etc/passwd

2,
如何將文本文件的每行作爲字符串送入一個變量?
引用 :
就是對一行文本送入一個字符串變量,而後下一行再作一樣動做,應該是個循壞。目標爲了把想要下載的軟件放在一個文本中,而後從另外一個文本中找本上面這些軟件包 REQUIRE 的其它包,而後生成一個下載列表,讓 FTP 程序安刻列表自動去下載。
解答參考 :
引用 :
若是把一行文本送入一個字符串變量,能夠採用直接賦值的方式。如:
AA= "This is a example"
若是要把 xxxx.txt 文件不一樣的行賦值給同一個變量,能夠用 awk
cat xxxx.txt | awk '{ AA = $0 }'
而後在 awk 內部加上對 AA 變量進行處理的函數。
其中將文件中每行賦給一個變量的方法爲 :
代碼 :
zhyfly@zhyfly:~/bash$ cat 1
xaAsdfasfABC...
21A32ABC...
xxxxABC...
zhyfly@zhyfly:~/bash$ cat 1|awk '{a[x++]=$0}END{for(i=0;i<NR;i++)print i,a[i]}'
0 xaAsdfasfABC...
1 21A32ABC...
2 xxxxABC...
zhyfly@zhyfly:~/bash$
3,如何把漢字變成相似"%AC%5B"的符號?
引用 :
我編 bash script 程序用 wget 下載文件,但有些文件名是中文的,必需把這些中文文件名寫成這樣的格式,如 "%AC%A1" 。怎樣把漢字變成這樣的編碼呢?多謝!
解答參考 :( 利用 xxd,tr,sed 命令 )
引用 :
我卻是能夠把漢字轉成 encode 格式:
xie 0$ echo
論壇 | tr -d "\n" | xxd -i | sed -e "s/ 0x/%/g" | tr -d " ,\n"
%c2%db%cc%b3
大寫的:
xie 0$ echo
論壇 | tr -d "\n" | xxd -i | sed -e "s/ 0x/%/g" | tr -d " ,\n" | tr "[a-f]" "[A-F]"
%C2%DB%CC%B3
不過這會把 url 中容許的正常字符一塊兒編碼,因此還要改爲只轉 url 中不容許的字符才行。
4,怎樣將\n換成換行符??
引用 :
例若有文本以下:
abcd\nabcde
cdef\nmmmini
qqqmad\nnnnnnn

\n 換成換行符後應是:
abcd
abcde
cdef
mmmini
qqqmad
nnnnnn

如何作??
解答參考 :
a,
直接利用 sed
代碼 :
zhyfly@zhyfly:~/bash$ cat escape
abcd\nabcde
cdef\nmmmini
qqqmad\nnnnnnn
zhyfly@zhyfly:~/bash$ cat escape|sed 's/\\n/\
> /g'
abcd
abcde
cdef
mmmini
qqqmad
nnnnnn
zhyfly@zhyfly:~/bash$
b,sed 後再利用 tr
代碼 :
zhyfly@zhyfly:~/bash$ cat escape|sed 's/\\n/@/g'|tr '@' '\n'
5, 怎麼替換行中的某一不肯定字段??
引用 :
現有一文本文件 . 內容以下 :
/root/text #mysql
#KILL
/root/big #you
/root/ghg

/root/lll

'
Sed 命令 . 我能夠刪除 "#KILL" 和空行 .
可是在 /root/text 後面的 #mysql /root/big 後面的 #you 這兩個字段我怎麼刪除呢 ??
#mysql
#you 是不肯定的字段 . 了就是說 # 後面能夠跟任意的字段名稱 , 而不必定是 mysql you
感受好像 SED 就是用來進行行操做的 .
解答參考 :
代碼 :
zhyfly@zhyfly:~/bash$ cat mysql
/root/text #mysql
#KILL
/root/big #you
/root/ghg
 
/root/lll
zhyfly@zhyfly:~/bash$ sed 's/#.*//g' mysql # 還去掉空行的話就sed -e 's/#.*//g' -e '/^$/d' mysql
/root/text
 
/root/big
/root/ghg
 
/root/lll
zhyfly@zhyfly:~/bash$ sed 's/#.*//g' mysql
6,如何理解sed -e 's/^\([a-zA-Z]\+\) \([a-zA-Z]\+\)\(.*\)/\2 \1\3/g' file?
解答參考:
首先
引用 :
加號表示至少匹配一次。

\?
等表示引用前面的第 ? 個匹配 .
其次
引用 :
意思以下:
在文件每一行的開始,若是在第一個空格以前只含有英文字符,那麼與空格以後的以英文字符開頭截止到最後一個英文字符的字符串進行對換,例如
First Second1234....
變爲 Second First1234....

後面的數字爲替代符,順序表明前面那三個括號裏的表達式, 1 就是第一個括號裏的內容,以此類推,那麼原有順序 \1 \2\3 就被替換爲 \2 \1\3 ,因此就是一二表達式替換而已
7,如何刪除換行符?
引用 :
我想將幾行合併成一行如何刪除換行符或回車符??
解答參考 :
a,
腳本 script
代碼 :
#!/bin/bash
for i in `cat file`
do
echo -n $i
done
b,sed
代碼 :
echo $(cat file)|sed 's/ //g'
c,tr
代碼 :
cat 1|tr -d '\n';echo
8,如何求列最大值?
具體:
引用 :
除了逐行比較 , 還有什麼辦法麼 ?
3q
有沒有現成的 sh
解答參考 :
引用 :
代碼 :
tmp文件中第一列中最大值,tmp文件以下:
javalee//home/javalee/lx>cat tmp
12      343
534     3445
4       34
7765    3
44      5
9       9
3       59
845     576
2589    45
35      9.9
8i      123
3       3
2       3576
3       856
4       5
javalee//home/javalee/lx>cat tmp|awk '{print $1}'|sort -n|sed -n '$p'       # 執行
7765    # 結果
思路 : awk tmp 第一列數據 , sort 排序以後 ( 由小到大 ), sed 顯示末行 ( 即排序後最大的數值 )
9,如何在AWK裏面把數據添加到文件裏?
引用 :
好比在 END 塊裏面把數組內容寫到一個文件裏面去。
解答參考 :
引用 :
javalee//home/javalee/lx>cat data
Mike Harrington:[510) 548-1278:250:100:175
Christian Dobbins:[408) 538-2358:155:90:201
Susan Dalsass:[206) 654-6279:250:60:50
Archie McNichol:[206) 548-1348:250:100:175
Jody Savage:[206) 548-1278:15:188:150
Guy Quigley:[916) 343-6410:250:100:175
Dan Savage:[406) 298-7744:450:300:275
Nancy McNeil:[206) 548-1278:250:80:75
John Goldenrod:[916) 348-4278:250:100:175
Chet Main:[510) 548-5258:50:95:135
Tom Savage:[408) 926-3456:250:168:200
Elizabeth Stachelin:[916) 440-1763:175:75:300
javalee//home/javalee/lx>awk -F: '{name[x++]=$1};END{for(i=0;i<NR;i++)print i,name[i]}' data >tmp #
取文件中 $1 域中的值做爲數組 , 在輸出到文件 tmp
javalee//home/javalee/lx>cat tmp
0 Mike Harrington
1 Christian Dobbins
2 Susan Dalsass
3 Archie McNichol
4 Jody Savage
5 Guy Quigley
6 Dan Savage
7 Nancy McNeil
8 John Goldenrod
9 Chet Main
10 Tom Savage
11 Elizabeth Stachelin
10,提取IP地址進入variable的問題
引用 :
我想寫一個 function ,提取 IP 地址進入 variable 。可是看過 grep sed 都好像尚未找到答案,用 awk 也不行,由於這一行字並不必定有這樣的 field 格式。

例如
You are browsing from 122.39.123.153 -> 122.39.123.153
So you wanna access 172.20.199.23? -> 172.20.199.23

我如今停留在:
extract=$($source | sed -n '/\([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\)/p')
11,怎麼查找對屬主用戶可讀的文件?
引用 :
關於 find 命令的問題 .
我發現 perm 選項要用三位數 , 好比 -perm 711 , 若是我不關心 group others 的權限 , 即這個三位數的後兩位可爲任意數 , 而對 user 必須是可執行的 ( 也有可能可讀 , 可寫 ). 我該用什麼選項呢 ?
或者我想找出 user 的權限位是 7, 而不關心 group others 的權限 , 該用什麼選項呢 ?
謝謝 .
解答參考 :
a,sed
代碼 :
ls -l|sed -n '/^.rwx.*/p'
b,find+grep
代碼 :
find . -exec ls -l {} \; |grep ^-rwx
12,如何快速把帶有大寫字母的文件名改成所有小寫?
解答參考:
a,script
vi change_name
代碼 :
#!/bin/bash
for f in *;do
mv $f `echo $f |tr "[A-Z]" "[a-z]"`
done
保存後在要轉換的目錄下執行
sh /path/to/change_name
b,rename
格式
代碼 :
rename source_pattern target_pattern source_files
13,怎樣在一個文件的特定的地方加入一點東西?
具體:
引用 :
好比我有一個文本文件的內容以下

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Red Hat 6.0 and later now use a font server independent of
# the X server to render fonts.
RgbPath "/usr/X11R6/lib/X11/rgb"
FontPath "unix/:7100"
EndSection

Section "Module"
Load "dbe"
Load "extmod"
Load "fbdevhw"
Load "glx"
Load "record"
Load "freetype"
Load "type1"
Load "dri"

如今我想在上面的紅字的下面加入一行 FontPath "/usr/fonts"
那麼在 shell 編程中應該如何操做呢?
還有我想在藍字的前面加入一個 # 鍵又該如何操做呢?
解答參考 :sed 或者 awk
代碼 :
cat add|sed -e '3a\FontPath "/uer/fonts"'
cat add|sed -e 's/Load "freetype"/#&/g'
14,怎樣在一個文件中讀一個值給變量?
引用 :
例如我有一個文件 line 的內容是 : 6 jor
如今我想提取裏面的 6 給一個變量 loop 以供它用 .
讀問怎麼樣實現 ?
SHELL 編程下 .
我試過 loop=more line 不行
loop=less line
也不行
解答參考 :
代碼 :
read loop foo < line
echo $loop
15,請問:怎麼讀出文件中的內容並輸出給scp調用?
引用 :
有一批 ip 地址的列表文件: 1.txt 2.txt 3.txt…… ,文件的內容以下:

$cat 1.txt

211.101.24.xxx
211.101.24.xx
211.100.25.xxx
211.100.25.xxx
...

其它的文件內容也相似,而後我但願實現一個 scp 操做,就是把某一個文件批量 scp 到一批服務器上,服務器 ip 列表從上述文件中的某一個讀取
補充 :scp ssh 的拷貝命令,用來在兩臺服務器之間拷貝文件,命令格式以下:
scp
源文件 目標服務器 ip :目的路徑
舉例以下:
$scp /home/guest/a 211.100.25.48:/etc/sysconfig/b.sh
這行命令將本機 /home/guest/ 下的文件 a 拷貝到遠程機器 211.100.25.48 /etc/sysconfig/ 下,並命名成 b.sh
解答參考 : 利用 for 循環
代碼 :
for i in $(cat 1.txt)
do
scp 源文件 $i 目標路徑/文件
done
16,指點一下 shell中的 模板替換功能!
引用 :
我想實現一個用模板文件中域的替換功能:
講不太清楚,看下面的例子:
templete.txt
------------------------------
Hello,<!--name-->!
where are you going?
I want to <!--where-->
------------------------------
以上是要使用的模板,其中有兩個域: <!--name--> <!--where-->

我有兩個變量: $NAME $WHERE
經過 sed 怎麼 把這兩變量提換到上面的域中,而且輸出到標準輸出中去?
解答參考 :
代碼 :
cat templete.txt|sed -e 1s/\<.*\>/$NAME/g
17,sedawk練習!
引用 :
現有文本文件格式以下:
--------------------------------------------------------------------
#It's a configurefile

Section "SystemCheck"

Package:x-window-system-core
Package:wmaker
Package:locales
Package:defoma
Package:x-ttcidfont-conf
Package:libft-perl
Package:libgtk1.2-common
Package:xlibs-dev

EndSection

Section "SoftwareConfig"

Package:XMMS
Package:Gimp
Package:xchat

EndSection
--------------------------------------------------------------------
要求:將該文件中的兩類 Package 分別讀入變量 systemlist softwarelist ,各 Package 名稱之間以空格分隔。

echo $systemlist 的結果以下:
x-window-system-core wmaker locales defoma x-ttcidfont-conf libft-perl libgtk1.2-common xlibs-dev
解答參考 :
代碼 :
systemlist=`cat sedawk|sed -n '/Section\ "SystemCheck"/,/EndSection/p'|awk -F: '{print $2}'`
or
代碼 :
systemlist=$(cat sedawk | sed -ne '/Section "SystemCheck"/,/EndSection/s/\(.*\)Package:\(.*\)/\2/p')
18,如何截短一個字符串?
引用 :
作一個批量更名的腳本(練手),碰到一個問題

##########################
#!/bin/sh
#batch file for filename convertion

for file in `ls`
do
mv $file $file.txt
done
##########################

這是一個很簡單的更名腳本,就是把 .txt 加到文件尾而已 .
若是要把一個文件名的後綴替換掉,好比
"001.rmvb" 改爲 "001.rm"
那麼怎麼處理這個字符串,把 .rmvb 去掉呢 ?
解答參考 :
代碼 :
ls|sed -e 's/^\(.*\)\.\(.*\)/\1/g'
另外截頭去尾還可使用
${variable#characters}
${variable##characters}
${variable%characters}
${variable%%characters}


19,
取值的問題?
引用 :
有一整數,格式爲: 12345678 ,我想把 12 賦值給 A 34 賦值給 B 5678 賦值 C ,請問用什麼命令能夠實現?
解答參考 :
a,sed
代碼 :
echo $s|sed 's/^\(..\)\(..\)\(.*\)$/\1 \2 \3/'
b,cut
代碼 :
echo $s|cut -c1-2
echo $s|cut -c3-4
echo $s|cut -c5-8
c,echo ${}
代碼 :
echo ${s:0:2}
echo ${s:2:2}
echo ${s:4:4}
20,格式轉換shell的問題?
引用 :
1TRF
2PNI
2PDE
1EGR
1ATX
1EPS
1ERG
1PNH
1EFM
1POU
2AT2
1ERP
1BAL
1HPB
2CBH
1SIS
1GAT
7I1B
1CDB
4TRX
1CIS
1TPM
1TFI
2CRD
1HCC
如今想把每一行都變成 pdb+ 上面每一行內容 +.Z
例如原本是 1HCC 的變成 pdb1HCC.Z ,這個 shell 該怎麼寫啊?
解答參考 :
a,sed
代碼 :
cat list|sed 's/\(.*\)/pdb\1\.Z/g'
b,
代碼 :
for i in $(cat list);do echo "pdb$i.Z";done>tmp;rm list;mv tmp list
21,如何用shell去處文件裏特定的行?
引用 :
例如
25%gfdghfhghgh

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

25%gfdkgjfkjgjkkk

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

25%agdfgdfgfdgg

qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
我該怎麼作才能把 25% 開始的那行和下面的一個空行去掉?
解答參考 :
a,sed
代碼 :
cat tmp|sed -e '/^25%/d' -e '/^$/d'
b, 刪除空行的方法 :
代碼 :
sed '/^$/d' file
tr -s "\n" file
for i in $(cat file);do echo $i;done
22,sed替換功能中變量如何表示?
引用 :
腳本以下:
#!/bin/bash

IP1=`cat /tmp/ip1`
IP2=`cat /tmp/ip2`

sed -e 's/$IP1/$IP2/g' /tmp/test.txt

此腳本未把 /tmp/test.txt 文件中的包含 /tmp/ip1 的內容字符替換爲 /tmp/ip2 中的字符
解答參考 :
代碼 :
sed -e s/${IP1}/${IP2}/g /tmp/test.txt
23,怎麼把大寫子母轉換成小寫?
引用 :
pdb1TRF.ent.Z
pdb2PNI.ent.Z
Apdb2PDE.ent.Z
pZdb1EGR.ent.Z
pdb1ATX.ent.Z
pdb1EPS.ent.Z
pdb1ERG.ent.Z
pdb1PNH.ent.Z
pdb1EFM.ent.Z
pdb1POU.ent.Z
pdb2AT2.ent.Z
Zpdb1ERP.ent.Z
Zpdb1BAL.ent.Z
須要把裏面除最後的 Z 之外的大寫子母改爲小寫該怎麼實現?
解答參考 :
a,sed
代碼 :
cat tmp|tr A-Z a-z|sed 's/z$/Z/g'
b,
代碼 :
for i in $(cat tmp|awk -F. '{print $1"."$2}');do echo "$(echo $i|tr A-Z a-z).Z";done
24,我要實現這個功能該怎麼作?
引用 :
個人家目錄有一個 Develop 目錄
1.
我想將該目錄下面的全部 java 文件選出
2.
找到做者是個人文件 (@author jimmy)
3.
最後在這些文件中搜索全部包含有 Hashmap 的行
(
固然也能夠考慮直接將他改成 HashMap)

我是這麼作的 ,
find /home/jimmy/Develop -name "*java*" -exec grep jimmy -l {} \;
這麼作的結果是完成了前兩步 . 輸出以下
/home/jimmy/Develop/Users.java
/home/jimmy/Develop/Services.java
/home/jimmy/Develop/Status.java

我想使用 :
find /home/jimmy/Develop -name "*java*" -exec grep jimmy -l {} \; | grep Hashmap -n
卻行不通
解答參考 :
代碼 :
grep Hashmap -n `find /home/jimmy/Develop -exec grep jimmy -l {} \;`
代碼 :
ls -l|grep username|find . -name "filename"|xargs grep -l "string"
代碼 :
sed -ne 's/Hashmap/HashMap/gp' `find /home/jimmy/Develop -exec grep jimmy -l {} \;`
25,怎樣轉換如下文檔??
引用 :
轉換如下文檔 :

Joey: What, like there's a rule or something?

(The door buzzer sounds and Chandler gets it.)

Chandler: Please don't do that again, it's a horrible sound.

Paul: (over the intercom) It's, uh, it's Paul.

Monica: Oh God, is it 6:30? Buzz him in!

Joey: Who's Paul?

轉換成 :

{\bf Joey:} What, like there's a rule or something?

(The door buzzer sounds and Chandler gets it.)

{\bf Chandler:} Please don't do that again, it's a horrible sound.

{\bf Paul:} (over the intercom) It's, uh, it's Paul.

{\bf Monica:} Oh God, is it 6:30? Buzz him in!

{\bf Joey:} Who's Paul?
解答參考 :
代碼 :
cat tmp|sed 's/^\([[:alpha:]]*:\)/{\\bf\ \1}/g'
26,請問如何統計一個文件中某個模式出現的次數??
解答參考:grep tr
代碼 :
cat file|tr " " "\n"|grep -wc "matchpattern"
27,求一Shell可以將文本文件中以特定字符串搜索到的行和它的下一行顯示出來。
解答參考:
a,sed
代碼 :
sed -n '/pattern/{N;p}' file
b,grep
代碼 :
grep -A1 'pattern' file
28,如何將一個輸出中的若干行分別賦值給變量?
引用 :
好比一個命令輸出裏面有 3
a
bbb
ccccccc

分別賦值給變量 a1,a2,a3 ,能夠麼?若是輸出更多,建立的變量也相應越多?

還有,如何讀取一個文本文件中的若干行呢,和上面同樣,分別賦值,能夠麼?
解答參考 :
代碼 :
for i in $(cat file);do eval a$n=$i;((n+=1)); done
29,有一批文件,裏面都有共同內容的一行文本,能編一個腳本,把它們都刪除嗎?
引用 :
是這樣的,有一個學習 php4 .chm 格式的文件,因在 Linux 下沒法看,我在 WIN 下用反編譯工具保存爲 *.html 格式。因爲反編譯工具未註冊,這樣生成的 *.html 文件裏面都有一行提示,原文件內容以下 :
<br> This file is decompiled by an unregistered version of ChmDecompiler.<br> Regsitered version does not show this message. <br>You can download ChmDecompiler at : <a href="http://www.etextwizard.com/" target=_blank>http://www.etextwizard.com/</a><br><br>
我想把全部這些文件內的上述提示去掉,用腳本能作到嗎,應怎樣實現,還有更好的方法嗎 ?
解答參考 :
scirpt:
代碼 :
#!/bin/bash
for file in *.html
do
sed -e '/This file is decompiled/d' > temp
rm $file
mv temp $file
done
引用 :
sed '/aa/s/abc/arg/' filename
這個命令是用來替換文本的,可是我想問,若是在這條語句的前面有一個變量,我想用這個變量的值來替換文件中的知足條件的字符串,用 sed 如何來作?由於在單引號中的變量不能替換。
若是用 sed 不行,是否還有取代的辦法?
解答參考 : 假設 arg 爲變量
代碼 :
sed /aa/s/abc/$arg/ filename
sed '/aa/s/abc/'$arg'/' filename
sed "/aa/s/abc/$arg/" filename
tr
代碼 :
$var=newstr
$cat urfile|tr oldstr $var
 
31. 幾種shell裏的小括號,大括號結構和有括號的變量,命令的用法
在這裏我想說的是幾種 shell 裏的小括號 , 大括號結構和有括號的變量,命令的用法,以下:
PHP 代碼 :
1. ${var}
2. $( cmd )
3. () {}
4. ${var:- string },${var:+ string },${var:= string },${var:? string }
5. $(( exp ))
6. $(var% pattern ),$(var%% pattern ),$(var #pattern),$(var##pattern) 

如今分述以下:
1.Shell
中變量的原形: ${var}
你們常見的變量形式都是 $var,
PHP 代碼 :
$ var= test
$ echo  $var
test 

但當你要顯示變量值加隨意的字符 ( 我這裏用 AA) 時,就會出錯,以下:
PHP 代碼 :
$ echo  $varAA



這時應該用變量的原形: ${var} ,便是加一個大括號來限定變量名稱的範圍,以下
PHP 代碼 :
$ echo ${var} AA
testAA


以這個特性,咱們能夠很方便地寫一個批量改後綴名的程序,我把它命名爲 mymv ,程序以下:
PHP 代碼 :
#!/bin/bash
 
tail =$ 1
for  filename in  ` ls `
do
   
mv $filename  ${ filename }. $tail
done 

程序須要提供一個後綴名,如 c ,表示改成後綴爲 c C 程序文件,看下面的測試:
PHP 代碼 :
ls
a b c
mymv c
ls
a
. c b . c c . c


看樣子程序運行的很好,但這是不完善的程序,有 2 個要注意的問題:
A,
目錄下沒有子目錄,若是有一個目錄,假設爲 dir ,則也會被改成 dir.c ,這顯然不是咱們想要的,應該修正這個程序能識別目錄。
B,
沒有幫助對程序的參數進行處理,程序應該足夠友好,在用戶沒有給定後綴名時應能處理,像上面的將直接給文件加上了一個點 (.), 這顯然也不是咱們想要的。

由於咱們的目的是說明 ${var} ,這樣已經足夠了,所以這裏不會再對上面的程序進行修正。

2.
命令替換 $(cmd)
命令替換 $(cmd) 和符號 `cmd`( 注意這不是單引號,在美式鍵盤上, ` ESC 下面的那個鍵 ) 有相同之處
PHP 代碼 :
ls
a b c
$ echo $( ls )
a b c
$ echo ` ls `
a b c 

咱們來分析一下命令 echo $(ls) ,以便理解所謂命令替換是什麼意思:
shell
掃描一遍命令行,發現了 $(cmd) 結構,便將 $(cmd) 中的 cmd 執行一次,獲得其標準輸出,再將此輸出放到原來命令 echo $(ls) 中的 $(ls) 位置,即替換了 $(ls), 再執行 echo 命令。
以下:
echo $(ls)
被替換成了 echo a b c
這裏要注意的是 $(cmd) 中的命令的錯誤輸出是不會被替換的,替換的只是標準輸出:
PHP 代碼 :
$ var=$( cat d )      ### 文件d在當前目錄不存在
cat d 沒有那個文件或目錄
$ echo  $var

$        ### 顯然var變量的值是空的 

3. 一串的命令執行 () {}
()
{} 都是對一串的命令進行執行,但有所區別:
A,()
只是對一串命令從新開一個子 shell 進行執行
B,{}
對一串命令在當前 shell 執行
C,()
{} 都是把一串的命令放在括號裏面,而且命令之間用 ; 號隔開
D,()
最後一個命令能夠不用分號
E,{}
最後一個命令要用分號
F,{}
的第一個命令和左括號之間必需要有一個空格
G,()
裏的各命令沒必要和括號有空格
H,()
{} 中括號裏面的某個命令的重定向隻影響該命令,但括號外的重定向則影響到括號裏的全部命令

咱們來看幾個例子:
PHP 代碼 :
$ var= test
$ (var= notest ; echo  $var )        ### 變量var值爲notest,此是在子shell中有效
notest
$ echo  $var         ### shell中值仍爲test
test
$ { var= notest ; echo  $var ;}      ### 注意左括號和var之間要有一個空格
notest
$ echo  $var                      ### shell中的var變量的值變爲了notest
notest
$ {  var1 = test1 ; var2 = test2 ;echo  $var1 > a ;echo  $var2 ;}     ### 輸出test1被重定向到文件a中,
test2                 ### test2輸出則仍輸出到標準輸出中。
cat a
test1
$ {  var1 = test1 ; var2 = test2 ;echo  $var1 ;echo  $var2 ;}> a              ### 括號內命令的標準輸出所有被重定向到文件a中
cat a
test1
test2 

4, 幾種特殊的替換結構: ${var:-string},${var:+string},${var:=string},${var:?string}
A,${var:-string}
${var:=string}
若變量 var 爲空,則用在命令行中用 string 來替換 ${var:-string} ,不然變量 var 不爲空時,則用變量 var 的值來替換 ${var:-string}
如:
PHP 代碼 :
$ echo  newvar

$ echo ${ newvar :- a }
a
$ echo  newvar              ### 變量newvar的值仍然是空,但上一命令行中${newvar:-a}被替換成了a

newvar = b
$ echo ${ newvar :- a }        ### 變量newvar的值不爲空時,此命令行中的${newvar:-b}被替換爲$newvar,即b
b


對於 ${var:=string} 的替換規則和 ${var:-string} 是同樣的,所不一樣之處是 ${var:=string} var 爲空時,用 string 替換 ${var:=string} 的同時,把 string 賦給變量 var
PHP 代碼 :
$ echo  newvar

$ echo ${ newvar := a }
a
$ echo  newvar            ### 變量newvar被賦值爲a,同時${newvar:=a}被替換成a
a
$ echo ${ newvar := b }      ### 變量newvar不爲空(其值已被賦爲a),則${newvar:=b}被替換爲newvar的值(即b)
a
$ echo  $newvar


${var:=string} 很經常使用的一種用法是,判斷某個變量是否賦值,沒有的話則給它賦上一個默認值。
如設置默認的編輯器:
PHP 代碼 :
echo  You  use  editor : ${ EDITOR :=/ bin / vi

B,${var:+string}
${var:+string}
的替換規則和上面的相反,即只有當 var 不是空的時候才替換成 string ,若 var 爲空時則不替換或者說是替換成變量 var 的值,即空值。 ( 由於變量 var 此時爲空,因此這兩種說法是等價的 )
PHP 代碼 :
$ echo  $newvar
a
$ echo ${ newvar :+ b }
b
$ echo  $newvar
a
newvar =
$ echo ${
newvar :+ b }



C,${var:?string}
替換規則爲:若變量 var 不爲空,則用變量 var 的值來替換 ${var:?string} ;若變量 var 爲空,則把 string 輸出到標準錯誤中,並從腳本中退出。咱們可利用此特性來檢查是否設置了變量的值。
PHP 代碼 :
newvar =
$ echo ${
newvar :? 沒有設置newvar的值 }
bash newvar 沒有設置newvar的值
newvar = a
$ echo ${ newvar :? 沒有設置newvar的值 }
a


補充擴展:在上面這五種替換結構中 string 不必定是常值的,可用另一個變量的值或是一種命令的輸出。
PHP 代碼 :
$ echo ${var:-` date `}
 3月 6 02 : 10 : 39 CST 2005
$ echo ${var:-$( date )}
 3月 6 02 : 11 : 46 CST 2005
a = test
$ echo ${var:- $a }
test


5.POSIX 標準的擴展計算 :$((exp))
這種計算是符合 C 語言的運算符,也就是說只要符合 C 的運算符均可用在 $((exp)) ,甚至是三目運算符。
注意:這種擴展計算是整數型的計算,不支持浮點型 . 如果邏輯判斷,表達式 exp 爲真則爲 1, 假則爲 0
PHP 代碼 :
$ echo $(( 3 + 2 ))
5
$ echo $(( 3 > 2 ))
1
$ echo $(( 25 < 2 : 3 ))
3
$ echo  $var

$ echo $((var= 2 + 3 ))
5
$ echo  $var
5
$ echo $((var++))
5
$ echo  $var
6


好了,上面的例子足夠了,這也代表了這種擴展運算是很強大的。

6.
四種模式匹配替換結構: ${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
這四種結構的意義是: ${var%pattern} ${var%%pattern} 表示從最右邊 ( 即結尾 ) 匹配的, ${var#pattern} ${var##pattern} 從最左邊 ( 即開頭 ) 匹配的。其中 ${var%pattern} ${var#pattern} 是最短匹配, ${var%%pattern} ${var##pattern} 是最長匹配。只有在 pattern 中使用了通配符纔能有最長最短的匹配,不然沒有最長最短匹配之分。

結構中的 pattern 支持通配符, * 表示零個或多個任意字符, ? 表示零個或一個任意字符, [...] 表示匹配中括號裏面的字符, [!...] 表示不匹配中括號裏面的字符。
PHP 代碼 :
$ var= aabbbccbbdbb
$ echo ${var% b }
aabbbccbbdb
$ echo ${var%% b }
aabbbccbbdb
$ echo ${var #a}
abbbccbbdbb
$ echo ${var ##a}
abbbccbbdbb
$ echo ${var%* b }
aabbbccbbdb
$ echo ${var%%* b }

$ echo ${var
#a*}
abbbccbbdbb
$ echo ${var ##a*}



上面是簡單的例舉四種模式匹配替換結構的用法。
32.bash中字符串的處理
1. 獲得字符串長度
方法一 :
$echo ${#variable}
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ #x}
14 

方法二 :
$expr length "$variable"
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr length  "$x"
14 

方法三 :
$expr "$variable" : ".*"
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr  "$x"  ".*"
14 

2. 查找字符串子串位置
方法 :
$expr index "$variable" "substring"
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr index  "$x" "is"
3
zhyfly
: ~$  expr index  "$x" "t"


(ps: 若是出現重複 , 好象只能查到第一個 , 第二個 , 第三個 ,..., 怎麼查到呢 ???)
3.
獲得字符串子字符串
方法一 :
$echo ${variable:position:length}
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x : 1 : 5 }
his i 

方法二 :
$expr substr "$variable" startposition length
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr substr  "$x"  1 5
this 

(ps: 注意方法一和方法二中位置的區別 !)
4.
匹配正則表達式之匹配長度
方法 :
$expr match "$x" "string"
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$  expr match  "$x" "his"
0
zhyfly
: ~$  expr match  "$x" "this"
4
zhyfly
: ~$  expr match  "$x" "."


5. 字符串的掐頭去尾
方法 :
$echo ${variable#startletter*endletter} # #
表示掐頭 , 由於鍵盤上 # $ 前面 , 一個表示最小匹配
$echo ${variable##tartletter*endletter}
兩個表示最大匹配
$echo ${variable%startletter*endletter} # %
表示去尾 , 由於鍵盤上 % $ 後面 , 一個表示最小匹配
$echo ${variable%%startletter*endletter}
兩個表示最大匹配
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x #t}
his is a test
zhyfly
: ~$ echo ${ x #t*h}
is is a test
zhyfly
: ~$ echo ${ x #t*s}
 
is a test

zhyfly
: ~$ echo ${ x ##t*s}
t

zhyfly
: ~$ echo ${ x % t }
this is a tes
zhyfly
: ~$ echo ${ x % s * t }
this is a te
zhyfly
: ~$ echo ${ x % e * t }
this is a t

zhyfly
: ~$ echo ${ x %% i * t }
th 

6. 字符 ( ) 的替換
方法 :
$echo ${variable/oldletter/newletter} #
替換一個
$echo ${variable//oldletter/newletter} #
替換全部
code:
PHP 代碼 :
zhyfly : ~$  x = "this is a test"
zhyfly : ~$ echo ${ x / i / m }
thms is a test
zhyfly
: ~$ echo ${ x //i/m}
thms ms a test 
相關文章
相關標籤/搜索