在西單圖書大廈閑溜達茫蛹,發(fā)現(xiàn)了一個日本計算機雜志的中文版操刀,《Software Design》,一直有學(xué)習(xí)Shell的想法婴洼,覺得自己在Linux環(huán)境下工作的效率簡直弱成渣骨坑。。柬采。
以下是摘錄的筆記(邊讀邊寫欢唾,結(jié)果發(fā)現(xiàn)差不多把試讀的部分抄了一遍。粉捻。):
第1章 sed和awk超級入門
為了把多個命令組合起來使用礁遣,人們進一步發(fā)展了在OS設(shè)計之初就有的標(biāo)準(zhǔn)輸入輸出的想法,從而出現(xiàn)了作為命令組合手段的“管道”結(jié)構(gòu)肩刃。
標(biāo)準(zhǔn)輸入輸出是一種在程序被執(zhí)行時亡脸,OS可以自動地分配輸入、輸出以及錯誤輸出設(shè)備的機制树酪。
OS在程序啟動時會執(zhí)行一種叫做startup routine的共通的初始化處理浅碾。在這個處理中準(zhǔn)備好標(biāo)準(zhǔn)輸入輸出以便于使用。標(biāo)準(zhǔn)狀態(tài)的分配是這樣的:輸入設(shè)備(標(biāo)準(zhǔn)輸入)是鍵盤续语,輸出設(shè)備(標(biāo)準(zhǔn)輸出)以及錯誤輸出設(shè)備(標(biāo)準(zhǔn)錯誤輸出)是終端垂谢。
-
shell和重定向:
- 用戶輸入命令,系統(tǒng)會解釋輸入的命令字符串疮茄,生成進程滥朱,把命令的執(zhí)行結(jié)果顯示出來。
- shell的重定向功能:
-
>
變更標(biāo)準(zhǔn)輸出的輸出位置力试,如輸出位置文件已經(jīng)存在徙邻,那么會先刪除文件的所有內(nèi)容 ,再把新內(nèi)容寫到文件中去畸裳。 -
>>
變更標(biāo)準(zhǔn)輸出的輸出位置缰犁,追加文件內(nèi)容 -
<
變更標(biāo)準(zhǔn)輸入的輸入方。
-
管道是輸入輸出的想法進一步發(fā)展的結(jié)果,是為了實現(xiàn)某個命令的標(biāo)準(zhǔn)輸出直接作為另一個命令的輸入而提供的單向數(shù)據(jù)流機制帅容。標(biāo)準(zhǔn)shell一般用符號
|
來表示管道颇象。commandA | commandB
就是表示A的標(biāo)準(zhǔn)輸出作為B的標(biāo)準(zhǔn)輸入來使用。在管道中流通的數(shù)據(jù)成為“流”是單純的字節(jié)流并徘,并沒有像“行“這樣的數(shù)據(jù)分割概念遣钳。空管道讀入(從管道的輸入側(cè)輸入數(shù)據(jù)),直到能有數(shù)據(jù)讀出為止,讀入處理都是加鎖的。另外,由于輸出側(cè)的命令不能從管道讀入數(shù)據(jù)等原因,OS 在內(nèi)部為管道預(yù)留的緩存都滿了的情況下,(從管道輸出側(cè)讀入數(shù)據(jù)直到緩存為空為止)對管道的寫入操作也是加鎖的麦乞。
利用管道吧多個命令組合起來使用時蕴茴,為了讓多個命令都順場地使用數(shù)據(jù),一般只使用由ASCII碼構(gòu)成的文本數(shù)據(jù)姐直。
對標(biāo)準(zhǔn)輸入中輸入的數(shù)據(jù)進行加工荐开,并在標(biāo)準(zhǔn)輸出中進行輸出的命令叫“過濾器”命令。sed和awk也是為了加工數(shù)據(jù)流而做成的文本加工過濾器命令简肴。
sed基本以行為單位來處理輸入數(shù)據(jù)
-
cat '/etc/passwd | sed "s!/bin/bash$!/usr/local/bin/bash!g"
使用sed替換字符串- 最后的
$
表示作為替換對象的/bin/bash處于行尾晃听。 - 因為替換對象的字符串中包含
"/"
,所以沒有采用sed的標(biāo)準(zhǔn)記述法"/"
砰识,而是用"!"
- 最后的
-
awk會實現(xiàn)把輸入的數(shù)據(jù)根據(jù)字段單位進行分割能扒,如果沒有指定分割單位,以輸入數(shù)據(jù)中的空格或者tab為分隔符對數(shù)據(jù)進行分割辫狼。
awk ' BEGIN { FS=":" } { shells[$NF]++; } END { for(i in shells) print i ":" shells[i]; }' /etc/passwd
BEGIN
節(jié)是在開始讀入輸入行之前要執(zhí)行的處理初斑。用FS=":"
把字段分隔符給為:
。awk用變量NF
來保存輸入行的字段數(shù)膨处,$NF
可以用來發(fā)問最后一個字符段的值见秤。END
節(jié)記述的是在所有的輸入行讀入完成之后要執(zhí)行的處理。 grep這個詞原本就是表示一個叫做ed的編輯器的命令文法真椿,它表示把g(Global=把整個文件作為對象)用re(Regular Expression)p(print)出來鹃答。
-
通過給LANG環(huán)境變量設(shè)置適當(dāng)?shù)闹担ㄖ到y(tǒng)和命令可以使用的字符編碼突硝。
echo $LANG > en_US.UTF-8
第2章 sed詳解及用法
- 命令:
-
s
: 進行字符串替換; -
d
: 刪除测摔; -
p
: 數(shù)據(jù)輸出; -
y
: 替換1個字符解恰; -
w
: 文件輸出锋八; -
n
: 文件輸入。
-
- s命令:字符串替換:
$ sed -e 's/源字符串/[替換后的字符串]/[標(biāo)志]' 輸入.txt
-
$ sed -e 's/aaa//g' input.txt
-> aaa被刪除 - 源字符串可以用正則表達時表示护盈,如果包含"/"挟纱,可以用""進行轉(zhuǎn)義,或者用其他字符替換腐宋。
- [ 替換后的字符串 ]中出現(xiàn)"&"時表示和查找字符串一樣紊服。
sed -e 's/aaa/+&+/g' input.txt
-> aaa被替換成+aaa+ - 標(biāo)志可以指定為:g(Global) / p(print) / w (write):
-
g
把文章整體作為替換范圍時使用
$ sed -e 's/bbb/aaa/g' input.txt
$ sed -g -e 's/bbb/aaa/' input.txt
注意-g要在-e前面
兩個命令的效果一樣 -
p
只表示發(fā)生替換的行檀轨,不過默認(rèn)情況下不管是不是發(fā)生替換sed都會把輸入數(shù)據(jù)輸出到標(biāo)準(zhǔn)輸出,如果只加標(biāo)志"p",會輸出兩行相同的內(nèi)容围苫〉闫铮可以在sed啟動時加上"-n"選項來控制標(biāo)準(zhǔn)輸出改橘。 -
w
如果想把替換后的結(jié)果寫到文件中可以使用w標(biāo)志。
$ sed -e 's/aaa/eee/gw output.txt' input.txt
此時在output.txt只輸出匹配的行慰照,如果同時還想輸出不匹配的行剃盾,使用"w"命令會更簡單
$ sed -e 's/aa/eee/g' -e 'w output.txt' input.txt
指定了多個-e腳本
-
-
- y命令:替換1個字符
$ sed -e 'y/abc/xyz/' input.txt
-> a=>x, b=>y, c=>z - d命令: 刪除
d命令是刪除指定行腺占,并將剩余行進行輸出的命令。
$ sed -e '1,2d' input.txt
-> 刪除第1痒谴,2 行
如果省略地址就表示刪除所有行衰伯,輸出結(jié)果邊為空;只執(zhí)行d命令輸入文件不會變化积蔚。 - 地址
地址列 | 表示的含義 |
---|---|
(未指定) | 所有數(shù)據(jù) |
3 | 第三行 |
20,$ | 從第20行開始到最后一行 |
10,5 | 第10行(第2個數(shù)字<=第1個數(shù)字的情況) |
/^[0-9]/ | 所有以數(shù)字開頭的行 |
15,/Z$/ | 從第15行開始到以Z結(jié)尾的行為止 |
5,10! | 5~10行以外 |
-
指定多個命令
命令之間用分號 ; 分割
$ sed -e '2d;s/aaa/eee/g' input.txt
-> 刪除第2行意鲸,然后,全局替換aaa為eee或者尽爆,在sed的啟動選項中怎顾,通過i多個-e腳本
$ sed -e '2d' -e 's/aaa/eee/g' input.txt
-
文件輸出
- 用
>
重定向到文件 - 用w命令寫到文件
- 在sed啟動時加上
-i
選項,將處理結(jié)果覆蓋到原文件中漱贱。甚至還可以將處理前的數(shù)據(jù)作為備份文件保存起來
$ sed -i.bak -e 's/bbb/eee/' input.txt
-->生成備份文件input.txt.bak槐雾,替換內(nèi)容保存在input.txt 中
- 用
-
雙引號與單引號
- “, /, $, `, \ 都是特殊字符,在使用sed指定腳本時幅狮,為了不作為特殊字符處理募强,需要用單引號’ 括起來。
- 用雙引號可以使用shell變量
sed -e "s/$HOSTNAME/new_hostname/g" /etc/hosts
- 雙引號使用特殊字符時需要用\進行轉(zhuǎn)義
腳本文件的讀取和執(zhí)行
sed -f 腳本文件 輸入文件
如果制定多個-f選項崇摄,則按照指定的順序從文件中讀取腳本進行執(zhí)行擎值。
# sample.sed
1,3s/aaa/eee/g
3d
$ sed -f sample.sed input.txt
命令的組合
{ ... }
1, 3{
s/aaa/eee/g
y/abc/xyz/
p
}標(biāo)簽/分支處理/循環(huán)處理
指定方法 | 所表示的內(nèi)容 |
---|---|
:label名 | 指定標(biāo)簽,label名在腳本中是唯一的 |
b label名 | 無條件跳轉(zhuǎn)到label名指定的命令進行執(zhí)行 |
條件 b label名 | 輸入行滿足條件時逐抑,跳轉(zhuǎn)到label名指定的命令進行執(zhí)行幅恋。 如果指定"/模式/b 標(biāo)簽",輸入行和模式匹配時泵肄,跳轉(zhuǎn)到label名指定的命令進行執(zhí)行 |
條件 !b label名 | 輸入行不滿足條件時捆交,跳轉(zhuǎn)到label名指定的命令進行執(zhí)行。 如果指定"/模式/b 標(biāo)簽"腐巢,輸入行和模式不匹配時品追,跳轉(zhuǎn)到label名指定的命令進行執(zhí)行 |
t label名 | 讀入輸入行執(zhí)行命令,只有在使用s命令替換成功時才會跳轉(zhuǎn)到label名指定的命令進行執(zhí)行 |
T label名 | 讀入輸入行執(zhí)行命令冯丙,在使用s命令替換不成功時才會跳轉(zhuǎn)到label名指定的命令進行執(zhí)行 |
#分支示例
:label
command1
command2
/pattern/b label
command3
sed逐行處理讀入數(shù)據(jù)并處理肉瓦,所以不擅長跨行處理遭京。
#循環(huán)示例
:loop
N <--字符串合并
$!b loop <--不是最后一行
s/\n//g