十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本節(jié)來介紹一些Pig常用的數(shù)據(jù)分析命令。
在博望等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站建設(shè)、成都做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作按需開發(fā)網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),營銷型網(wǎng)站,成都外貿(mào)網(wǎng)站制作,博望網(wǎng)站建設(shè)費(fèi)用合理。
1.load命令
load命令用來加載數(shù)據(jù)到指定的表結(jié)構(gòu),語法格式如下:
load '數(shù)據(jù)文件' [using PigStorage("分隔符")] as (表結(jié)構(gòu));
注意:默認(rèn)分隔符是制表符Tab,如果數(shù)據(jù)文件不是以Tab分割的,必須指定分隔符,否則加載數(shù)據(jù)失敗。例如:
A = load 'a.txt' as (id:int,name:chararray);
B = load 'b.txt' using PigStorage(",") as (id:int,name:chararray);
注意:等號=兩邊必須有空格,否則容易出錯(cuò)。
2.describe命令
describe命令用于查看表結(jié)構(gòu),語法格式如下:
describe 表名;
例如:
describe A;
3.group命令
group命令用來將數(shù)據(jù)分組,語法格式如下:
group 表名 by 字段名
例如:
C = group A by id;
4.foreach命令
foreach命令用來對數(shù)據(jù)集進(jìn)行迭代處理,語法格式如下:
foreach 表名 generate 字段列表
例如:
C = foreach A generate id,name;
也可以使用$0類似的命令來獲取數(shù)據(jù)集中的數(shù)據(jù):
C = foreach A generate 1;
5.filter命令
filter命令用來過濾數(shù)據(jù),語法格式如下:
filter A by 過濾條件
例如:
D = filter A by id == 'zs';
常用的條件表達(dá)式有:==, !=, =, =, ,
6.join命令
join命令用來連接兩張表,語法格式如下:
內(nèi)連接:join A by id,B by id;
外連接:
左外連接:join A by id left outer,B by id;
右外連接:join A by id right outer,B by id;
全外連接:join A by id full outer,B by id;
7.limit命令
limit命令用于取出有限大小的數(shù)據(jù)集,語法格式如下:
limit 表名 大小
例如:取出A中的前10條數(shù)據(jù)賦給B
B = limit A 10;
8.order命令
order命令用來對數(shù)據(jù)集按照指定字段排序,語法格式如下:
order 表名 by 字段列表 [desc]
默認(rèn)是正序排列,如需倒序在最后加上desc。例如:
B = order A by id;
B = order A by id desc, name desc;
9.split命令
split命令用來根據(jù)條件切分?jǐn)?shù)據(jù)集,語法格式如下:
split 表名 into 子表1 if 條件1[,子表2 if 條件2, ……]
例如:
split A into A1 if id=10, A2 if (id10 and id=20), A3 if id20;
10.union命令
union命令用來合并兩個(gè)數(shù)據(jù)集,語法格式如下:
union 表1,表2;
例如:
C = union A, B;
注意:union要求這兩個(gè)數(shù)據(jù)集的結(jié)構(gòu)一樣,或者能隱式轉(zhuǎn)換成一樣,否則操作失敗。
11.exec命令
exec命令用于執(zhí)行pig腳本,語法格式如下:
exec [-param param_name=param_value] [-param_file file_name] [script];
示例1:顯示和運(yùn)行腳本
grunt cat myscript.pig;
a = LOAD 'student' AS (name, age, gpa);
b = LIMIT a 3;
DUMP b;
grunt exec myscript.pig;
(alice,20,2.47)
(luke,18,4.00)
(holly,24,3.27)
示例2:帶參數(shù)運(yùn)行命令
grunt cat myscript.pig;
a = LOAD 'student' AS (name, age, gpa);
b = ORDER a BY name;
STORE b into '$out';
grunt exec –param out=myoutput myscript.pig;
示例3:帶多個(gè)參數(shù)運(yùn)行命令
grunt exec –param p1=myparam1 –param p2=myparam2 myscript.pig;
12.run命令
run命令也是用來執(zhí)行pig腳本的,語法格式如下:
run [-param param_name=param_value] [-param_file file_name] script;
示例1:顯示和運(yùn)行腳本
grunt cat myscript.pig;
b = ORDER a BY name;
c = LIMIT b 10;
grunt a = LOAD 'student' AS (name, age, gpa);
grunt run myscript.pig;
grunt d = LIMIT c 3;
grunt DUMP d;
(alice,20,2.47)
(alice,27,1.95)
(alice,36,2.27)
示例2:帶參數(shù)運(yùn)行命令
grunt a = LOAD 'student' AS (name, age, gpa);
grunt cat myscript.pig;
b = ORDER a BY name;
STORE b into '$out';
grunt run –param out=myoutput myscript.pig;
13.set命令
set命令用于給key設(shè)置值,語法格式如下:
set key 'value';
例如:
set name ‘xiaoming’;
14.kill命令
kill命令用于殺死進(jìn)程,語法格式如下:
kill jobid;
15.help命令
help命令用于列出pig命令及屬性,格式如下:
-help [properties]
16.quit命令
quit命令用于退出Grunt Shell環(huán)境,格式如下:
quit;
17.clear命令
clear命令用來清屏,語法格式如下:
clear;
18.history命令
history命令用來查看執(zhí)行命令記錄,語法格式如下:
history;
19.distinct命令
distinct命令用來刪除數(shù)據(jù)集中的重復(fù)項(xiàng),語法格式如下:
distinct 表名;
例如:
B = distinct A;
20.dump命令
dump命令用來將結(jié)果數(shù)據(jù)集顯示到屏幕上,格式如下:
dump 表名;
例如:
dump A;
21.store命令
store命令用于將結(jié)果數(shù)據(jù)集保存到文件中,格式如下:
store 表名 into '文件路徑' [using PigStorage('分隔符')];
例如:
store A into '/pig/output/A.txt';
store A into '/pig/output/A.txt' using PigStorage(',');
store命令與load命令一樣,默認(rèn)分隔符為Tab,如需更改分隔符,需要手動指定。
總結(jié)
常用的Pig命令就是以上這些了,在執(zhí)行Pig命令時(shí),需要注意以下幾點(diǎn)內(nèi)容:
PigLatin語句末尾一定要加分號【;】。
Pig對命令的大小寫沒有規(guī)定,可以使用大寫,也可以小寫。
Pig中的函數(shù)就必須使用大寫,因?yàn)檫@些函數(shù)在pig中定義的時(shí)候就是大寫。
針對Pig處理過程中的臨時(shí)變量的名稱,大小寫也是有區(qū)分的。
在pig中執(zhí)行的命令其實(shí)并不會真正的執(zhí)行,只有當(dāng)執(zhí)行dump或者store命令的時(shí)候才會真正指定之前定義的命令。
如果某一條命令執(zhí)行失敗了,那么只需要修改這條命令,重新執(zhí)行即可。
sed 編輯器是 Linux 系統(tǒng)管理員的工具包中最有用的資產(chǎn)之一
Linux 操作系統(tǒng)最大的一個(gè)好處是它帶有各種各樣的實(shí)用工具。存在如此之多不同的實(shí)用工具,幾乎不可能知道并了解所有這些工具??梢院喕P(guān)鍵情況下操作的一個(gè)實(shí)用 工具是 sed。它是任何管理員的工具包中最強(qiáng)大的工具之一,并且可以證明它自己在關(guān)鍵情況下非常有價(jià)值。
sed 實(shí)用工具是一個(gè)“編輯器”,但它與其它大多數(shù)編輯器不同。除了不面向屏幕之外,它還是非交互式的。這意味著您必須將要對數(shù)據(jù)執(zhí)行的命令插入到命令行或要處 理的腳本中。當(dāng)顯示它時(shí),請忘記您在使用 Microsoft Word 或其它大多數(shù)編輯器時(shí)擁有的交互式編輯文件功能。sed 在一個(gè)文件(或文件集)中非交互式、并且不加詢問地接收一系列的命令并執(zhí)行它們。因而,它流經(jīng)文本就如同水流經(jīng)溪流一樣,因而 sed 恰當(dāng)?shù)卮砹肆骶庉嬈鳌K梢杂脕韺⑺谐霈F(xiàn)的 "Mr. Smyth" 修改為 "Mr. Smith",或?qū)?"tiger cub" 修改為 "wolf cub"。流編輯器非常適合于執(zhí)行重復(fù)的編輯,這種重復(fù)編輯如果由人工完成將花費(fèi)大量的時(shí)間。其參數(shù)可能和一次性使用一個(gè)簡單的操作所需的參數(shù)一樣有限, 或者和一個(gè)具有成千上萬行要進(jìn)行編輯修改的腳本文件一樣復(fù)雜。sed 是 Linux 和 UNIX 工具箱中最有用的工具之一,且使用的參數(shù)非常少。
sed 的工作方式
sed 實(shí)用工具按順序逐行將文件讀入到內(nèi)存中。然后,它執(zhí)行為該行指定的所有操作,并在完成請求的修改之后將該行放回到內(nèi)存中,以將其轉(zhuǎn)儲至終端。完成了這一行 上的所有操作之后,它讀取文件的下一行,然后重復(fù)該過程直到它完成該文件。如同前面所提到的,默認(rèn)輸出是將每一行的內(nèi)容輸出到屏幕上。在這里,開始涉及到 兩個(gè)重要的因素—首先,輸出可以被重定向到另一文件中,以保存變化;第二,源文件(默認(rèn)地)保持不被修改。sed 默認(rèn)讀取整個(gè)文件并對其中的每一行進(jìn)行修改。不過,可以按需要將操作限制在指定的行上。
該實(shí)用工具的語法為:
sed [options] '{command}' [filename]
在這篇文章中,我們將瀏覽最常用的命令和選項(xiàng),并演示它們?nèi)绾喂ぷ鳎约八鼈冞m于在何處使用。
替換命令
sed 實(shí)用工具以及其它任何類似的編輯器的最常用的命令之一是用一個(gè)值替換另一個(gè)值。用來實(shí)現(xiàn)這一目的的操作的命令部分語法是:
's/{old value}/{new value}/'
因而,下面演示了如何非常簡單地將 "tiger" 修改為 "wolf":
$ echo The tiger cubs will meet on Tuesday after school | sed
's/tiger/wolf/'
The wolf cubs will meet on Tuesday after school
$
注意如果輸入是源自之前的命令輸出,則不需要指定文件名—同樣的原則也適用于 awk、sort 和其它大多數(shù) LinuxUNIX 命令行實(shí)用工具程序。
多次修改
如果需要對同一文件或行作多次修改,可以有三種方法來實(shí)現(xiàn)它。第一種是使用 "-e" 選項(xiàng),它通知程序使用了多條編輯命令。例如:
$ echo The tiger cubs will meet on Tuesday after school | sed -e '
s/tiger/wolf/' -e 's/after/before/'
The wolf cubs will meet on Tuesday before school
$
這是實(shí)現(xiàn)它的非常復(fù)雜的方法,因此 "-e" 選項(xiàng)不常被大范圍使用。更好的方法是用分號來分隔命令:
$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/; s/after/before/'
The wolf cubs will meet on Tuesday before school
$
注 意分號必須是緊跟斜線之后的下一個(gè)字符。如果兩者之間有一個(gè)空格,操作將不能成功完成,并返回一條錯(cuò)誤消息。這兩種方法都很好,但許多管理員更喜歡另一種 方法。要注意的一個(gè)關(guān)鍵問題是,兩個(gè)撇號 (' ') 之間的全部內(nèi)容都被解釋為 sed 命令。直到您輸入了第二個(gè)撇號,讀入這些命令的 shell 程序才會認(rèn)為您完成了輸入。這意味著可以在多行上輸入命令—同時(shí) Linux 將提示符從 PS1 變?yōu)橐粋€(gè)延續(xù)提示符(通常為 "")—直到輸入了第二個(gè)撇號。一旦輸入了第二個(gè)撇號,并且按下了 Enter 鍵,則處理就進(jìn)行并產(chǎn)生相同的結(jié)果,如下所示:
$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/
s/after/before/'
The wolf cubs will meet on Tuesday before school
$
全局修改
讓我們開始一次看似簡單的編輯。假定在要修改的消息中出現(xiàn)了多次要修改的項(xiàng)目。默認(rèn)方式下,結(jié)果可能和預(yù)期的有所不同,如下所示:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/'
The tiger cubs will meet this Thursday at the same time
as the meeting last Tuesday
$
與 將出現(xiàn)的每個(gè) "Tuesday" 修改為 "Thursday" 相反,sed 編輯器在找到一個(gè)要修改的項(xiàng)目并作了修改之后繼續(xù)處理下一行,而不讀整行。sed 命令功能大體上類似于替換命令,這意味著它們都處理每一行中出現(xiàn)的第一個(gè)選定序列。為了替換出現(xiàn)的每一個(gè)項(xiàng)目,在同一行中出現(xiàn)多個(gè)要替換的項(xiàng)目的情況下, 您必須指定在全局進(jìn)行該操作:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/g'
The tiger cubs will meet this Thursday at the same time
as the meeting last Thursday
$
請記住不管您要查找的序列是否僅包含一個(gè)字符或詞組,這種對全局化的要求都是必需的。
sed 還可以用來修改記錄字段分隔符。例如,以下命令將把所有的 tab 修改為空格:
sed 's// /g'
其 中,第一組斜線之間的項(xiàng)目是一個(gè) tab,而第二組斜線之間的項(xiàng)目是一個(gè)空格。作為一條通用的規(guī)則,sed 可以用來將任意的可打印字符修改為任意其它的可打印字符。如果您想將不可打印字符修改為可打印字符—例如,鈴鐺修改為單詞 "bell"—sed 不是適于完成這項(xiàng)工作的工具(但 tr 是)。
有時(shí),您不想修改在一個(gè)文件中出現(xiàn)的所有指定項(xiàng)目。有時(shí),您只想在滿足某些條件時(shí)才作修改—例如,在與其它一些數(shù)據(jù)匹配之后才作修改。為了說明這一點(diǎn),請考慮以下文本文件:
$ cat sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
$
假定希望用 "2" 來替換 "1",但僅在單詞 "two" 之后才作替換,而不是每一行的所有位置。通過指定在給出替換命令之前必須存在一次匹配,可以實(shí)現(xiàn)這一點(diǎn):
$ sed '/two/ s/1/2/' sample_one
one 1
two 2
three 1
one 1
two 2
two 2
three 1
$
現(xiàn)在,使其更加準(zhǔn)確:
$ sed '
/two/ s/1/2/
/three/ s/1/3/' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
請 再次記住唯一改變了的是顯示。如果您查看源文件,您將發(fā)現(xiàn)它始終保持不變。您必須將輸出保存至另一個(gè)文件,以實(shí)現(xiàn)永久保存。值得重復(fù)的是,不對源文件作修 改實(shí)際是禍中有?!屇軌?qū)ξ募M(jìn)行試驗(yàn)而不會造成任何實(shí)際的損害,直到讓正確命令以您預(yù)期和希望的方式進(jìn)行工作。
以下命令將修改后的輸出保存至一個(gè)新的文件:
$ sed '
/two/ s/1/2/
/three/ s/1/3/' sample_one sample_two
該輸出文件將所有修改合并在其中,并且這些修改通常將在屏幕上顯示?,F(xiàn)在可以用 head、cat 或任意其它類似的實(shí)用工具來進(jìn)行查看。
腳本文件
sed 工具允許您創(chuàng)建一個(gè)腳本文件,其中包含從該文件而不是在命令行進(jìn)行處理的命令,并且 sed 工具通過 "-f" 選項(xiàng)來引用。通過創(chuàng)建一個(gè)腳本文件,您能夠一次又一次地重復(fù)運(yùn)行相同的操作,并指定比每次希望從命令行進(jìn)行處理的操作詳細(xì)得多的操作。
考慮以下腳本文件:
$ cat sedlist
/two/ s/1/2/
/three/ s/1/3/
$
現(xiàn)在可以在數(shù)據(jù)文件上使用腳本文件,獲得和我們之前看到的相同的結(jié)果:
$ sed -f sedlist sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
注意當(dāng)調(diào)用 "-f" 選項(xiàng)時(shí),在源文件內(nèi)或命令行中不使用撇號。腳本文件,也稱為源文件,對于想重復(fù)多次的操作和從命令行運(yùn)行可能出錯(cuò)的復(fù)雜命令很有價(jià)值。編輯源文件并修改一個(gè)字符比在命令行中重新輸入一條多行的項(xiàng)目要容易得多。
限制行
編輯器默認(rèn)查看輸入到流編輯器中的每一行,且默認(rèn)在輸入到流編輯器中的每一行上進(jìn)行編輯。這可以通過在發(fā)出命令之前指定約束條件來進(jìn)行修改。例如,只在此示例文件的輸出的第 5 和第 6 行中用 "2" 來替換 "1",命令將為:
$ sed '5,6 s/1/2/' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
在這種情況下,因?yàn)橐薷牡男惺菍iT指定的,所以不需要替換命令。因此,您可以靈活地根據(jù)匹配準(zhǔn)則(可以是行號或一種匹配模式)來選擇要修改哪些行(從根本上限制修改)。
禁止顯示
sed 默認(rèn)將來自源文件的每一行顯示到屏幕上(或重定向到一個(gè)文件中),而無論該行是否受到編輯操作的影響,"-n" 參數(shù)覆蓋了這一操作。"-n" 覆蓋了所有的顯示,并且不顯示任何一行,而無論它們是否被編輯操作修改。例如:
$ sed -n -f sedlist sample_one
$
$ sed -n -f sedlist sample_one sample_two
$ cat sample_two
$
在 第一個(gè)示例中,屏幕上不顯示任何東西。在第二個(gè)示例中,不修改任何東西,因此不將任何東西寫到新的文件中—它最后是空的。這不是否定了編輯的全部目的嗎? 為什么這是有用的?它是有用的僅因?yàn)?"-n" 選項(xiàng)能夠被一條顯示命令 (-p) 覆蓋。為了說明這一點(diǎn),假定現(xiàn)在像下面這樣對腳本文件進(jìn)行了修改:
$ cat sedlist
/two/ s/1/2/p
/three/ s/1/3/p
$
然后下面是運(yùn)行它的結(jié)果:
$ sed -n -f sedlist sample_one
two 2
three 3
two 2
two 2
three 3
$
保持不變的行全部不被顯示。只有受到編輯操作影響的行被顯示了。在這種方式下,可以僅取出這些行,進(jìn)行修改,然后把它們放到一個(gè)單獨(dú)的文件中:
$ sed -n -f sedlist sample_one sample_two
$
$ cat sample_two
two 2
three 3
two 2
two 2
three 3
$
利用它的另一種方法是只顯示一定數(shù)量的行。例如,只顯示 2-6 行,同時(shí)不做其它的編輯修改:
$ sed -n '2,6p' sample_one
two 1
three 1
one 1
two 1
two 1
$
其它所有的行被忽略,只有 2-6 行作為輸出顯示。這是一項(xiàng)出色的功能,其它任何工具都不能容易地實(shí)現(xiàn)。Head 將顯示一個(gè)文件的頂部,而 tail 將顯示一個(gè)文件的底部,但 sed 允許從任意位置取出想要的任意內(nèi)容。
刪除行
用一個(gè)值替換另一個(gè)值遠(yuǎn)非流編輯器可以執(zhí)行的唯一功能。它還具有許多的潛在功能,在我看來第二種最常用的功能是刪除。刪除與替換的工作方式相同,只是它刪除指定的行(如果您想要?jiǎng)h除一個(gè)單詞而不是一行,不要考慮刪除,而應(yīng)考慮用空的內(nèi)容來替換它—s/cat//)。
該命令的語法是:
'{what to find} d'
從 sample_one 文件中刪除包含 "two" 的所有行:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
從顯示屏中刪除前三行,而不管它們的內(nèi)容是什么:
$ sed '1,3 d' sample_one
one 1
two 1
two 1
three 1
$
只顯示剩下的行,前三行不在顯示屏中出現(xiàn)。對于流編輯器,一般當(dāng)它們涉及到全局表達(dá)式時(shí),特別是應(yīng)用于刪除操作時(shí),有幾點(diǎn)要記?。?/p>
上三角號 (^) 表示一行的開始,因此,如果 "two" 是該行的頭三個(gè)字符,則
sed '/^two/ d' sample_one
將只刪除該行。
美元符號 ($) 代表文件的結(jié)尾,或一行的結(jié)尾,因此,如果 "two" 是該行的最后三個(gè)字符,則
sed '/two$/ d' sample_one
將只刪除該行。
將這兩者結(jié)合在一起的結(jié)果:
sed '/^$/ d' {filename}
刪除文件中的所有空白行。例如,以下命令將 "1" 替換為 "2",以及將 "1" 替換為 "3",并刪除文件中所有尾隨的空行:
$ sed '/two/ s/1/2/; /three/ s/1/3/; /^$/ d' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
其通常的用途是刪除一個(gè)標(biāo)題。以下命令將刪除文件中所有的行,從第一行直到第一個(gè)空行:
sed '1,/^$/ d' {filename}
添加和插入文本
可以結(jié)合使用 sed 和 "a" 選項(xiàng)將文本添加到一個(gè)文件的末尾。實(shí)現(xiàn)方法如下:
$ sed '$a
This is where we stop
the test' sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
This is where we stop
the test
$
在該命令中,美元符號 ($) 表示文本將被添加到文件的末尾。反斜線 () 是必需的,它表示將插入一個(gè)回車符。如果它們被遺漏了,則將導(dǎo)致一個(gè)錯(cuò)誤,顯示該命令是錯(cuò)亂的;在任何要輸入回車的地方您必須使用反斜線。
要將這些行添加到第 4 和第 5 個(gè)位置而不是末尾,則命令變?yōu)椋?/p>
$ sed '3a
This is where we stop
the test' sample_one
one 1
two 1
three 1
This is where we stop
the test
one 1
two 1
two 1
three 1
$
這將文本添加到第 3 行之后。和幾乎所有的編輯器一樣,您可以選擇插入而不是添加(如果您希望這樣的話)。這兩者的區(qū)別是添加跟在指定的行之后,而插入從指定的行開始。當(dāng)用插入來代替添加時(shí),只需用 "i" 來代替 "a",如下所示:
$ sed '3i
This is where we stop
the test' sample_one
one 1
two 1
This is where we stop
the test
three 1
one 1
two 1
two 1
three 1
$
新的文本出現(xiàn)在輸出的中間位置,而處理通常在指定的操作執(zhí)行以后繼續(xù)進(jìn)行。
讀寫文件
重定向輸出的功能已經(jīng)演示過了,但需要指出的是,在編輯命令運(yùn)行期間可以同步地讀入和寫出文件。例如,執(zhí)行替換,并將 1-3 行寫到名稱為 sample_three 的文件中:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
1,3 w sample_three' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
$ cat sample_three
one 1
two 2
three 3
$
由于為 w (write) 命令指定了 "1,3",所以只有指定的行被寫到了新文件中。無論被寫的是哪些行,所有的行都在默認(rèn)輸出中顯示。
修改命令
除了替換項(xiàng)目之外,還可以將行從一個(gè)值修改為另一個(gè)值。要記住的是,替換是對字符逐個(gè)進(jìn)行,而修改功能與刪除類似,它影響整行:
$ sed '/two/ c
We are no longer using two' sample_one
one 1
We are no longer using two
three 1
one 1
We are no longer using two
We are no longer using two
three 1
$
修 改命令與替換的工作方式很相似,但在范圍上要更大些—將一個(gè)項(xiàng)目完全替換為另一個(gè)項(xiàng)目,而無論字符內(nèi)容或上下文??鋸堃稽c(diǎn)講,當(dāng)使用替換時(shí),只有字符 "1" 被字符 "2" 替換,而當(dāng)使用修改時(shí),原來的整行將被修改。在兩種情況下,要尋找的匹配條件都僅為 "two"。
修改全部但……
對于大多數(shù) sed 命令,詳細(xì)說明各種功能要進(jìn)行何種修改。利用感嘆號,可以在除指定位置之外的任何地方執(zhí)行修改—與默認(rèn)的操作完全相反。
例如,要?jiǎng)h除包含單詞 "two" 的所有行,操作為:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
而要?jiǎng)h除除包含單詞 "two" 的行之外的所有行,則語法變?yōu)椋?/p>
$ sed '/two/ !d' sample_one
two 1
two 1
two 1
$
如果您有一個(gè)文件包含一系列項(xiàng)目,并且想對文件中的每個(gè)項(xiàng)目執(zhí)行一個(gè)操作,那么首先對那些項(xiàng)目進(jìn)行一次智能掃描并考慮將要做什么是很重要的。為了使事情變得更簡單,您可以將 sed 與任意迭代例程(for、while、until)結(jié)合來實(shí)現(xiàn)這一目的。
比如說,假定您有一個(gè)名為 "animals" 的文件,其中包含以下項(xiàng)目:
pig
horse
elephant
cow
dog
cat
您希望運(yùn)行以下例程:
#mcd.ksh
for I in $*
do
echo Old McDonald had a $I
echo E-I, E-I-O
done
結(jié) 果將為,每一行都顯示在 "Old McDonald has a" 的末尾。雖然對于這些項(xiàng)目的大部分這是正確的,但對于 "elephant" 項(xiàng)目,它有語法錯(cuò)誤,因?yàn)榻Y(jié)果應(yīng)當(dāng)為 "an elephant" 而不是 "a elephant"。利用 sed,您可以在來自 shell 文件的輸出中檢查這種語法錯(cuò)誤,并通過首先創(chuàng)建一個(gè)命令文件來即時(shí)地更正它們:
#sublist
/ a a/ s/ a / an /
/ a e/ s/ a / an /
/a i/ s / a / an /
/a o/ s/ a / an /
/a u/ s/ a / an /
然后執(zhí)行以下過程:
$ sh mcd.ksh 'cat animals' | sed -f sublist
現(xiàn) 在,在運(yùn)行了 mcd 腳本之后,sed 將在輸出中搜索單個(gè)字母 a (空格,"a",空格)之后緊跟了一個(gè)元音的任意位置。如果這種位置存在,它將把該序列修改為空格,"an",空格。這樣就使問題更正后才顯示在屏幕上, 并確保各處的編輯人員在晚上可以更容易地入睡。結(jié)果是:
Old McDonald had a pig
E-I, E-I-O
Old McDonald had a horse
E-I, E-I-O
Old McDonald had an elephant
E-I, E-I-O
Old McDonald had a cow
E-I, E-I-O
Old McDonald had a dog
E-I, E-I-O
Old McDonald had a cat
E-I, E-I-O
提前退出
sed 默認(rèn)讀取整個(gè)文件,并只在到達(dá)末尾時(shí)才停止。不過,您可以使用退出命令提前停止處理。只能指定一條退出命令,而處理將一直持續(xù)直到滿足調(diào)用退出命令的條件。
例如,僅在文件的前五行上執(zhí)行替換,然后退出:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
5q' sample_one
one 1
two 2
three 3
one 1
two 2
$
在退出命令之前的項(xiàng)目可以是一個(gè)行號(如上所示),或者一條查找/匹配命令:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
/three/q' sample_one
one 1
two 2
three 3
$
您 還可以使用退出命令來查看超過一定標(biāo)準(zhǔn)數(shù)目的行,并增加比 head 中的功能更強(qiáng)的功能。例如,head 命令允許您指定您想要查看一個(gè)文件的前多少行—默認(rèn)數(shù)為 10,但可以使用從 1 到 99 的任意一個(gè)數(shù)字。如果您想查看一個(gè)文件的前 110 行,您用 head 不能實(shí)現(xiàn)這一目的,但用 sed 可以:
sed 110q filename
處理問題
當(dāng)使用 sed 時(shí),要記住的重要事項(xiàng)是它的工作方式。它的工作方式是:讀入一行,在該行上執(zhí)行它已知要執(zhí)行的所有任務(wù),然后繼續(xù)處理下一行。每一行都受給定的每一個(gè)編輯命令的影響。
如果您的操作順序沒有十分徹底地考慮清楚,那么這可能會很麻煩。例如,假定您需要將所有的 "two" 項(xiàng)目修改為 "three",然后將所有的 "three" 修改為 "four":
$ sed '
/two/ s/two/three/
/three/ s/three/four/' sample_one
one 1
four 1
four 1
one 1
four 1
four 1
four 1
$
最初讀取的 "two" 被修改為 "three"。然后它滿足為下一次編輯建立的準(zhǔn)則,從而變?yōu)?"four"。最終的結(jié)果不是想要的結(jié)果—現(xiàn)在除了 "four" 沒有別的項(xiàng)目了,而本來應(yīng)該有 "three" 和 "four"。
當(dāng)執(zhí)行這種操作時(shí),您必須非常用心地注意指定操作的方式,并按某種順序來安排它們,使得操作之間不會互相影響。例如:
$ sed '
/three/ s/three/four/
/two/ s/two/three/' sample_one
one 1
three 1
four 1
one 1
three 1
three 1
four 1
$
這非常有效,因?yàn)?"three" 值在 "two" 變成 "three" 之前得到修改。
標(biāo)簽和注釋
可以在 sed 腳本文件中放置標(biāo)簽,這樣一旦文件變得龐大,可以更容易地說明正在發(fā)生的事情。存在各種各樣與這些標(biāo)簽相關(guān)的命令,它們包括:
接下來的步驟
訪問并收藏 Linux 技術(shù)中心
閱讀 Dale Dougherty 和 Arnold Robbins 的著作 sed awk, 2nd Edition (O'Reilly Associates 出版社)。
: 冒號表示一個(gè)標(biāo)簽名稱。例如:
:HERE
以冒號開始的標(biāo)簽可以由 "b" 和 "t" 命令處理。
b {label} 充當(dāng) "goto" 語句的作用,將處理發(fā)送至前面有一個(gè)冒號的標(biāo)簽。例如,
b HERE
將處理發(fā)送給行
:HERE
如果緊跟 b 之后沒有指定任何標(biāo)簽,則處理轉(zhuǎn)至腳本文件的末尾。
t {label} 只要自上次輸入行或執(zhí)行一次 "t" 命令以來進(jìn)行了替換操作,就轉(zhuǎn)至該標(biāo)簽。和 "b" 一樣,如果沒有給定標(biāo)簽名,則處理轉(zhuǎn)至腳本文件的末尾。
# 符號作為一行的第一個(gè)字符將使整行被當(dāng)作注釋處理。注釋行與標(biāo)簽不同,不能使用 b 或 t 命令來轉(zhuǎn)到注釋行上。
在linux中我們刪除文件可以直接使用rm命令來刪除哦,小編今天給大家介紹介紹在linux 刪除文件和目錄及誤刪除之后文件恢復(fù)方法,有需要了解的同學(xué)可參考。
前面你已經(jīng)學(xué)習(xí)了使用 touch 命令來創(chuàng)建文件,以及使用 mkdir 命令來創(chuàng)建目錄 tigger。
現(xiàn)在,你需要學(xué)習(xí)如何刪除文件和目錄。 使用 rm 命令來刪除文件和目錄是一個(gè)直截了當(dāng)?shù)倪^程。詳情請參閱 rm 的說明書頁。刪除文件和目錄的選項(xiàng)包括:
? -i — 互動。提示你確認(rèn)刪除。這個(gè)選項(xiàng)可以幫助你避免誤刪文件。
? -f — 強(qiáng)制。代替互動模式,不提示地刪除文件。除非你知道自己在干什么,使用這個(gè)選項(xiàng)通常不是明智之舉。
? -v — 詳細(xì)。顯示文件的刪除進(jìn)度。
? -r — 遞歸。將會刪除某個(gè)目錄及其中所有的文件和子目錄。
要使用 rm 命令來刪除文件 piglet.txt,鍵入:
rm piglet.txt
警告
一旦文件或目錄使用 rm 命令刪除后,它就一去不復(fù)返了。
使用 -i(互動)選項(xiàng)會再給你一次機(jī)會來決定你是否真的想刪除該文件。
rm -i piglet.txt
rm: 是否刪除一般文件‘piglet.txt’?
你還可以使用通配符“*”來刪除文件,不過,你必須謹(jǐn)慎而為,因?yàn)樗苋菀讋h除你并不想刪除的文件。
要使用通配符來刪除文件,可以鍵入:
rm pig*
上面的命令會刪除目錄中所有起首為 pig 字母的文件。
你還可以使用 rm 命令來刪除多個(gè)文件。 例如:
rm piglet.txt sneakers.txt
你可以使用 rmdir 來刪除目錄( 如:rmdir foo),但是目錄必須是空目錄。要使用 rm 來刪除目錄,你必須指定 -r 選項(xiàng)。
譬如,如果你想遞歸地刪除目錄 tigger,你可以鍵入:
rm -r tigger
如果你想組合選項(xiàng),例如強(qiáng)制一種遞歸的刪除,你可以鍵入:
rm -rf tigger
另一個(gè)比使用 rm 更安全的刪除目錄的命令是 rmdir 命令。這個(gè)命令不允許你使用遞歸刪除,因此不能刪除包含文件的目錄。
警告
rm 命令可以刪除你的整個(gè)文件系統(tǒng)!如果你登錄為根用戶,然后鍵入這個(gè)簡單命令: rm -rf /,你的麻煩就大了;這個(gè)命令會遞歸地刪除你的系統(tǒng)上的一切。
閱讀 rmdir 的說明書頁( man rmdir)來獲取關(guān)于這個(gè)命令的詳細(xì)信息
Linux 文件誤刪除恢復(fù)操作
一、用運(yùn)SecureCRT遠(yuǎn)程對操作系統(tǒng)上,查看一下當(dāng)前系統(tǒng)版本號,及文件系統(tǒng)格式
二、為方便本次實(shí)驗(yàn),我們新創(chuàng)建一文件。
三、執(zhí)行刪除操作,
四、運(yùn)用,系統(tǒng)自還工具debugfs來修復(fù)
五、打開,剛剛被刪除文件所在的分區(qū)
六、用ls 加-d參數(shù)顯示剛剛刪除文件所在的目錄
七、顯示有尖括號的就是我們要找的文件Inode 號 執(zhí)行l(wèi)ogdump –I 393289
八,執(zhí)行完命令后,顯示了一屏信息,我們需要的是下面這一行,并且要記住,后面的值
九,退出debugfs
十,執(zhí)行如下命令
十一,以上結(jié)果表示恢復(fù)成功我們看下/tmp目錄下到底有沒有
十二,tmp目錄下有我們顯示一下,
linux下刪除亂碼文件
根據(jù)inode 來修改或刪除linux 下亂碼的文件
1. 創(chuàng)建測試文件:
touch 1?.txt
2. 查詢inode :
[oracle@test]$ ll -i
total 14694452
17956913 -rw-r--r-- 1 oracle oinstall 0 Jan 18 20:24 1?.txt
3. 修改測試文件名:
find . -inum 17956913 -exec mv {} file.txt ;
4. 檢查修改結(jié)果
[oracle@test]$ ll
total 14694452
....
-rw-r--r-- 1 oracle oinstall 0 Jan 18 20:24 file.txt
記錄:刪除亂碼的文件可使用 find . -inum 17956913 -exec rm {} ;
sed 編輯器是 Linux 系統(tǒng)管理員的工具包中最有用的資產(chǎn)之一,
因此,有必要徹底地了解其應(yīng)用
Linux 操作系統(tǒng)最大的一個(gè)好處是它帶有各種各樣的實(shí)用工具。存在如此之多不同的實(shí)用工具,幾乎不可能知道并了解所有這些工具??梢院喕P(guān)鍵情況下操作的一個(gè)實(shí)用 工具是 sed。它是任何管理員的工具包中最強(qiáng)大的工具之一,并且可以證明它自己在關(guān)鍵情況下非常有價(jià)值。
sed 實(shí)用工具是一個(gè)“編輯器”,但它與其它大多數(shù)編輯器不同。除了不面向屏幕之外,它還是非交互式的。這意味著您必須將要對數(shù)據(jù)執(zhí)行的命令插入到命令行或要處 理的腳本中。當(dāng)顯示它時(shí),請忘記您在使用 Microsoft Word 或其它大多數(shù)編輯器時(shí)擁有的交互式編輯文件功能。sed 在一個(gè)文件(或文件集)中非交互式、并且不加詢問地接收一系列的命令并執(zhí)行它們。因而,它流經(jīng)文本就如同水流經(jīng)溪流一樣,因而 sed 恰當(dāng)?shù)卮砹肆骶庉嬈鳌K梢杂脕韺⑺谐霈F(xiàn)的 "Mr. Smyth" 修改為 "Mr. Smith",或?qū)?"tiger cub" 修改為 "wolf cub"。流編輯器非常適合于執(zhí)行重復(fù)的編輯,這種重復(fù)編輯如果由人工完成將花費(fèi)大量的時(shí)間。其參數(shù)可能和一次性使用一個(gè)簡單的操作所需的參數(shù)一樣有限, 或者和一個(gè)具有成千上萬行要進(jìn)行編輯修改的腳本文件一樣復(fù)雜。sed 是 Linux 和 UNIX 工具箱中最有用的工具之一,且使用的參數(shù)非常少。
sed 的工作方式
sed 實(shí)用工具按順序逐行將文件讀入到內(nèi)存中。然后,它執(zhí)行為該行指定的所有操作,并在完成請求的修改之后將該行放回到內(nèi)存中,以將其轉(zhuǎn)儲至終端。完成了這一行 上的所有操作之后,它讀取文件的下一行,然后重復(fù)該過程直到它完成該文件。如同前面所提到的,默認(rèn)輸出是將每一行的內(nèi)容輸出到屏幕上。在這里,開始涉及到 兩個(gè)重要的因素—首先,輸出可以被重定向到另一文件中,以保存變化;第二,源文件(默認(rèn)地)保持不被修改。sed 默認(rèn)讀取整個(gè)文件并對其中的每一行進(jìn)行修改。不過,可以按需要將操作限制在指定的行上。
該實(shí)用工具的語法為:
sed [options] '{command}' [filename]
在這篇文章中,我們將瀏覽最常用的命令和選項(xiàng),并演示它們?nèi)绾喂ぷ鳎约八鼈冞m于在何處使用。
替換命令
sed 實(shí)用工具以及其它任何類似的編輯器的最常用的命令之一是用一個(gè)值替換另一個(gè)值。用來實(shí)現(xiàn)這一目的的操作的命令部分語法是:
's/{old value}/{new value}/'
因而,下面演示了如何非常簡單地將 "tiger" 修改為 "wolf":
$ echo The tiger cubs will meet on Tuesday after school | sed
's/tiger/wolf/'
The wolf cubs will meet on Tuesday after school
$
注意如果輸入是源自之前的命令輸出,則不需要指定文件名—同樣的原則也適用于 awk、sort 和其它大多數(shù) LinuxUNIX 命令行實(shí)用工具程序。
多次修改
如果需要對同一文件或行作多次修改,可以有三種方法來實(shí)現(xiàn)它。第一種是使用 "-e" 選項(xiàng),它通知程序使用了多條編輯命令。例如:
$ echo The tiger cubs will meet on Tuesday after school | sed -e '
s/tiger/wolf/' -e 's/after/before/'
The wolf cubs will meet on Tuesday before school
$
這是實(shí)現(xiàn)它的非常復(fù)雜的方法,因此 "-e" 選項(xiàng)不常被大范圍使用。更好的方法是用分號來分隔命令:
$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/; s/after/before/'
The wolf cubs will meet on Tuesday before school
$
注 意分號必須是緊跟斜線之后的下一個(gè)字符。如果兩者之間有一個(gè)空格,操作將不能成功完成,并返回一條錯(cuò)誤消息。這兩種方法都很好,但許多管理員更喜歡另一種 方法。要注意的一個(gè)關(guān)鍵問題是,兩個(gè)撇號 (' ') 之間的全部內(nèi)容都被解釋為 sed 命令。直到您輸入了第二個(gè)撇號,讀入這些命令的 shell 程序才會認(rèn)為您完成了輸入。這意味著可以在多行上輸入命令—同時(shí) Linux 將提示符從 PS1 變?yōu)橐粋€(gè)延續(xù)提示符(通常為 "")—直到輸入了第二個(gè)撇號。一旦輸入了第二個(gè)撇號,并且按下了 Enter 鍵,則處理就進(jìn)行并產(chǎn)生相同的結(jié)果,如下所示:
$ echo The tiger cubs will meet on Tuesday after school | sed '
s/tiger/wolf/
s/after/before/'
The wolf cubs will meet on Tuesday before school
$
全局修改
讓我們開始一次看似簡單的編輯。假定在要修改的消息中出現(xiàn)了多次要修改的項(xiàng)目。默認(rèn)方式下,結(jié)果可能和預(yù)期的有所不同,如下所示:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/'
The tiger cubs will meet this Thursday at the same time
as the meeting last Tuesday
$
與 將出現(xiàn)的每個(gè) "Tuesday" 修改為 "Thursday" 相反,sed 編輯器在找到一個(gè)要修改的項(xiàng)目并作了修改之后繼續(xù)處理下一行,而不讀整行。sed 命令功能大體上類似于替換命令,這意味著它們都處理每一行中出現(xiàn)的第一個(gè)選定序列。為了替換出現(xiàn)的每一個(gè)項(xiàng)目,在同一行中出現(xiàn)多個(gè)要替換的項(xiàng)目的情況下, 您必須指定在全局進(jìn)行該操作:
$ echo The tiger cubs will meet this Tuesday at the same time
as the meeting last Tuesday | sed 's/Tuesday/Thursday/g'
The tiger cubs will meet this Thursday at the same time
as the meeting last Thursday
$
請記住不管您要查找的序列是否僅包含一個(gè)字符或詞組,這種對全局化的要求都是必需的。
sed 還可以用來修改記錄字段分隔符。例如,以下命令將把所有的 tab 修改為空格:
sed 's// /g'
其 中,第一組斜線之間的項(xiàng)目是一個(gè) tab,而第二組斜線之間的項(xiàng)目是一個(gè)空格。作為一條通用的規(guī)則,sed 可以用來將任意的可打印字符修改為任意其它的可打印字符。如果您想將不可打印字符修改為可打印字符—例如,鈴鐺修改為單詞 "bell"—sed 不是適于完成這項(xiàng)工作的工具(但 tr 是)。
有時(shí),您不想修改在一個(gè)文件中出現(xiàn)的所有指定項(xiàng)目。有時(shí),您只想在滿足某些條件時(shí)才作修改—例如,在與其它一些數(shù)據(jù)匹配之后才作修改。為了說明這一點(diǎn),請考慮以下文本文件:
$ cat sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
$
假定希望用 "2" 來替換 "1",但僅在單詞 "two" 之后才作替換,而不是每一行的所有位置。通過指定在給出替換命令之前必須存在一次匹配,可以實(shí)現(xiàn)這一點(diǎn):
$ sed '/two/ s/1/2/' sample_one
one 1
two 2
three 1
one 1
two 2
two 2
three 1
$
現(xiàn)在,使其更加準(zhǔn)確:
$ sed '
/two/ s/1/2/
/three/ s/1/3/' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
請 再次記住唯一改變了的是顯示。如果您查看源文件,您將發(fā)現(xiàn)它始終保持不變。您必須將輸出保存至另一個(gè)文件,以實(shí)現(xiàn)永久保存。值得重復(fù)的是,不對源文件作修 改實(shí)際是禍中有?!屇軌?qū)ξ募M(jìn)行試驗(yàn)而不會造成任何實(shí)際的損害,直到讓正確命令以您預(yù)期和希望的方式進(jìn)行工作。
以下命令將修改后的輸出保存至一個(gè)新的文件:
$ sed '
/two/ s/1/2/
/three/ s/1/3/' sample_one sample_two
該輸出文件將所有修改合并在其中,并且這些修改通常將在屏幕上顯示?,F(xiàn)在可以用 head、cat 或任意其它類似的實(shí)用工具來進(jìn)行查看。
腳本文件
sed 工具允許您創(chuàng)建一個(gè)腳本文件,其中包含從該文件而不是在命令行進(jìn)行處理的命令,并且 sed 工具通過 "-f" 選項(xiàng)來引用。通過創(chuàng)建一個(gè)腳本文件,您能夠一次又一次地重復(fù)運(yùn)行相同的操作,并指定比每次希望從命令行進(jìn)行處理的操作詳細(xì)得多的操作。
考慮以下腳本文件:
$ cat sedlist
/two/ s/1/2/
/three/ s/1/3/
$
現(xiàn)在可以在數(shù)據(jù)文件上使用腳本文件,獲得和我們之前看到的相同的結(jié)果:
$ sed -f sedlist sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
注意當(dāng)調(diào)用 "-f" 選項(xiàng)時(shí),在源文件內(nèi)或命令行中不使用撇號。腳本文件,也稱為源文件,對于想重復(fù)多次的操作和從命令行運(yùn)行可能出錯(cuò)的復(fù)雜命令很有價(jià)值。編輯源文件并修改一個(gè)字符比在命令行中重新輸入一條多行的項(xiàng)目要容易得多。
限制行
編輯器默認(rèn)查看輸入到流編輯器中的每一行,且默認(rèn)在輸入到流編輯器中的每一行上進(jìn)行編輯。這可以通過在發(fā)出命令之前指定約束條件來進(jìn)行修改。例如,只在此示例文件的輸出的第 5 和第 6 行中用 "2" 來替換 "1",命令將為:
$ sed '5,6 s/1/2/' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
在這種情況下,因?yàn)橐薷牡男惺菍iT指定的,所以不需要替換命令。因此,您可以靈活地根據(jù)匹配準(zhǔn)則(可以是行號或一種匹配模式)來選擇要修改哪些行(從根本上限制修改)。
禁止顯示
sed 默認(rèn)將來自源文件的每一行顯示到屏幕上(或重定向到一個(gè)文件中),而無論該行是否受到編輯操作的影響,"-n" 參數(shù)覆蓋了這一操作。"-n" 覆蓋了所有的顯示,并且不顯示任何一行,而無論它們是否被編輯操作修改。例如:
$ sed -n -f sedlist sample_one
$
$ sed -n -f sedlist sample_one sample_two
$ cat sample_two
$
在 第一個(gè)示例中,屏幕上不顯示任何東西。在第二個(gè)示例中,不修改任何東西,因此不將任何東西寫到新的文件中—它最后是空的。這不是否定了編輯的全部目的嗎? 為什么這是有用的?它是有用的僅因?yàn)?"-n" 選項(xiàng)能夠被一條顯示命令 (-p) 覆蓋。為了說明這一點(diǎn),假定現(xiàn)在像下面這樣對腳本文件進(jìn)行了修改:
$ cat sedlist
/two/ s/1/2/p
/three/ s/1/3/p
$
然后下面是運(yùn)行它的結(jié)果:
$ sed -n -f sedlist sample_one
two 2
three 3
two 2
two 2
three 3
$
保持不變的行全部不被顯示。只有受到編輯操作影響的行被顯示了。在這種方式下,可以僅取出這些行,進(jìn)行修改,然后把它們放到一個(gè)單獨(dú)的文件中:
$ sed -n -f sedlist sample_one sample_two
$
$ cat sample_two
two 2
three 3
two 2
two 2
three 3
$
利用它的另一種方法是只顯示一定數(shù)量的行。例如,只顯示 2-6 行,同時(shí)不做其它的編輯修改:
$ sed -n '2,6p' sample_one
two 1
three 1
one 1
two 1
two 1
$
其它所有的行被忽略,只有 2-6 行作為輸出顯示。這是一項(xiàng)出色的功能,其它任何工具都不能容易地實(shí)現(xiàn)。Head 將顯示一個(gè)文件的頂部,而 tail 將顯示一個(gè)文件的底部,但 sed 允許從任意位置取出想要的任意內(nèi)容。
刪除行
用一個(gè)值替換另一個(gè)值遠(yuǎn)非流編輯器可以執(zhí)行的唯一功能。它還具有許多的潛在功能,在我看來第二種最常用的功能是刪除。刪除與替換的工作方式相同,只是它刪除指定的行(如果您想要?jiǎng)h除一個(gè)單詞而不是一行,不要考慮刪除,而應(yīng)考慮用空的內(nèi)容來替換它—s/cat//)。
該命令的語法是:
'{what to find} d'
從 sample_one 文件中刪除包含 "two" 的所有行:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
從顯示屏中刪除前三行,而不管它們的內(nèi)容是什么:
$ sed '1,3 d' sample_one
one 1
two 1
two 1
three 1
$
只顯示剩下的行,前三行不在顯示屏中出現(xiàn)。對于流編輯器,一般當(dāng)它們涉及到全局表達(dá)式時(shí),特別是應(yīng)用于刪除操作時(shí),有幾點(diǎn)要記住:
上三角號 (^) 表示一行的開始,因此,如果 "two" 是該行的頭三個(gè)字符,則
sed '/^two/ d' sample_one
將只刪除該行。
美元符號 ($) 代表文件的結(jié)尾,或一行的結(jié)尾,因此,如果 "two" 是該行的最后三個(gè)字符,則
sed '/two$/ d' sample_one
將只刪除該行。
將這兩者結(jié)合在一起的結(jié)果:
sed '/^$/ d' {filename}
刪除文件中的所有空白行。例如,以下命令將 "1" 替換為 "2",以及將 "1" 替換為 "3",并刪除文件中所有尾隨的空行:
$ sed '/two/ s/1/2/; /three/ s/1/3/; /^$/ d' sample_one
one 1
two 1
three 1
one 1
two 2
two 2
three 1
$
其通常的用途是刪除一個(gè)標(biāo)題。以下命令將刪除文件中所有的行,從第一行直到第一個(gè)空行:
sed '1,/^$/ d' {filename}
添加和插入文本
可以結(jié)合使用 sed 和 "a" 選項(xiàng)將文本添加到一個(gè)文件的末尾。實(shí)現(xiàn)方法如下:
$ sed '$a
This is where we stop
the test' sample_one
one 1
two 1
three 1
one 1
two 1
two 1
three 1
This is where we stop
the test
$
在該命令中,美元符號 ($) 表示文本將被添加到文件的末尾。反斜線 () 是必需的,它表示將插入一個(gè)回車符。如果它們被遺漏了,則將導(dǎo)致一個(gè)錯(cuò)誤,顯示該命令是錯(cuò)亂的;在任何要輸入回車的地方您必須使用反斜線。
要將這些行添加到第 4 和第 5 個(gè)位置而不是末尾,則命令變?yōu)椋?/p>
$ sed '3a
This is where we stop
the test' sample_one
one 1
two 1
three 1
This is where we stop
the test
one 1
two 1
two 1
three 1
$
這將文本添加到第 3 行之后。和幾乎所有的編輯器一樣,您可以選擇插入而不是添加(如果您希望這樣的話)。這兩者的區(qū)別是添加跟在指定的行之后,而插入從指定的行開始。當(dāng)用插入來代替添加時(shí),只需用 "i" 來代替 "a",如下所示:
$ sed '3i
This is where we stop
the test' sample_one
one 1
two 1
This is where we stop
the test
three 1
one 1
two 1
two 1
three 1
$
新的文本出現(xiàn)在輸出的中間位置,而處理通常在指定的操作執(zhí)行以后繼續(xù)進(jìn)行。
讀寫文件
重定向輸出的功能已經(jīng)演示過了,但需要指出的是,在編輯命令運(yùn)行期間可以同步地讀入和寫出文件。例如,執(zhí)行替換,并將 1-3 行寫到名稱為 sample_three 的文件中:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
1,3 w sample_three' sample_one
one 1
two 2
three 3
one 1
two 2
two 2
three 3
$
$ cat sample_three
one 1
two 2
three 3
$
由于為 w (write) 命令指定了 "1,3",所以只有指定的行被寫到了新文件中。無論被寫的是哪些行,所有的行都在默認(rèn)輸出中顯示。
修改命令
除了替換項(xiàng)目之外,還可以將行從一個(gè)值修改為另一個(gè)值。要記住的是,替換是對字符逐個(gè)進(jìn)行,而修改功能與刪除類似,它影響整行:
$ sed '/two/ c
We are no longer using two' sample_one
one 1
We are no longer using two
three 1
one 1
We are no longer using two
We are no longer using two
three 1
$
修 改命令與替換的工作方式很相似,但在范圍上要更大些—將一個(gè)項(xiàng)目完全替換為另一個(gè)項(xiàng)目,而無論字符內(nèi)容或上下文??鋸堃稽c(diǎn)講,當(dāng)使用替換時(shí),只有字符 "1" 被字符 "2" 替換,而當(dāng)使用修改時(shí),原來的整行將被修改。在兩種情況下,要尋找的匹配條件都僅為 "two"。
修改全部但……
對于大多數(shù) sed 命令,詳細(xì)說明各種功能要進(jìn)行何種修改。利用感嘆號,可以在除指定位置之外的任何地方執(zhí)行修改—與默認(rèn)的操作完全相反。
例如,要?jiǎng)h除包含單詞 "two" 的所有行,操作為:
$ sed '/two/ d' sample_one
one 1
three 1
one 1
three 1
$
而要?jiǎng)h除除包含單詞 "two" 的行之外的所有行,則語法變?yōu)椋?/p>
$ sed '/two/ !d' sample_one
two 1
two 1
two 1
$
如果您有一個(gè)文件包含一系列項(xiàng)目,并且想對文件中的每個(gè)項(xiàng)目執(zhí)行一個(gè)操作,那么首先對那些項(xiàng)目進(jìn)行一次智能掃描并考慮將要做什么是很重要的。為了使事情變得更簡單,您可以將 sed 與任意迭代例程(for、while、until)結(jié)合來實(shí)現(xiàn)這一目的。
比如說,假定您有一個(gè)名為 "animals" 的文件,其中包含以下項(xiàng)目:
pig
horse
elephant
cow
dog
cat
您希望運(yùn)行以下例程:
#mcd.ksh
for I in $*
do
echo Old McDonald had a $I
echo E-I, E-I-O
done
結(jié) 果將為,每一行都顯示在 "Old McDonald has a" 的末尾。雖然對于這些項(xiàng)目的大部分這是正確的,但對于 "elephant" 項(xiàng)目,它有語法錯(cuò)誤,因?yàn)榻Y(jié)果應(yīng)當(dāng)為 "an elephant" 而不是 "a elephant"。利用 sed,您可以在來自 shell 文件的輸出中檢查這種語法錯(cuò)誤,并通過首先創(chuàng)建一個(gè)命令文件來即時(shí)地更正它們:
#sublist
/ a a/ s/ a / an /
/ a e/ s/ a / an /
/a i/ s / a / an /
/a o/ s/ a / an /
/a u/ s/ a / an /
然后執(zhí)行以下過程:
$ sh mcd.ksh 'cat animals' | sed -f sublist
現(xiàn) 在,在運(yùn)行了 mcd 腳本之后,sed 將在輸出中搜索單個(gè)字母 a (空格,"a",空格)之后緊跟了一個(gè)元音的任意位置。如果這種位置存在,它將把該序列修改為空格,"an",空格。這樣就使問題更正后才顯示在屏幕上, 并確保各處的編輯人員在晚上可以更容易地入睡。結(jié)果是:
Old McDonald had a pig
E-I, E-I-O
Old McDonald had a horse
E-I, E-I-O
Old McDonald had an elephant
E-I, E-I-O
Old McDonald had a cow
E-I, E-I-O
Old McDonald had a dog
E-I, E-I-O
Old McDonald had a cat
E-I, E-I-O
提前退出
sed 默認(rèn)讀取整個(gè)文件,并只在到達(dá)末尾時(shí)才停止。不過,您可以使用退出命令提前停止處理。只能指定一條退出命令,而處理將一直持續(xù)直到滿足調(diào)用退出命令的條件。
例如,僅在文件的前五行上執(zhí)行替換,然后退出:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
5q' sample_one
one 1
two 2
three 3
one 1
two 2
$
在退出命令之前的項(xiàng)目可以是一個(gè)行號(如上所示),或者一條查找/匹配命令:
$ sed '
/two/ s/1/2/
/three/ s/1/3/
/three/q' sample_one
one 1
two 2
three 3
$
您 還可以使用退出命令來查看超過一定標(biāo)準(zhǔn)數(shù)目的行,并增加比 head 中的功能更強(qiáng)的功能。例如,head 命令允許您指定您想要查看一個(gè)文件的前多少行—默認(rèn)數(shù)為 10,但可以使用從 1 到 99 的任意一個(gè)數(shù)字。如果您想查看一個(gè)文件的前 110 行,您用 head 不能實(shí)現(xiàn)這一目的,但用 sed 可以:
sed 110q filename
處理問題
當(dāng)使用 sed 時(shí),要記住的重要事項(xiàng)是它的工作方式。它的工作方式是:讀入一行,在該行上執(zhí)行它已知要執(zhí)行的所有任務(wù),然后繼續(xù)處理下一行。每一行都受給定的每一個(gè)編輯命令的影響。
如果您的操作順序沒有十分徹底地考慮清楚,那么這可能會很麻煩。例如,假定您需要將所有的 "two" 項(xiàng)目修改為 "three",然后將所有的 "three" 修改為 "four":
$ sed '
/two/ s/two/three/
/three/ s/three/four/' sample_one
one 1
four 1
four 1
one 1
four 1
four 1
four 1
$
最初讀取的 "two" 被修改為 "three"。然后它滿足為下一次編輯建立的準(zhǔn)則,從而變?yōu)?"four"。最終的結(jié)果不是想要的結(jié)果—現(xiàn)在除了 "four" 沒有別的項(xiàng)目了,而本來應(yīng)該有 "three" 和 "four"。
當(dāng)執(zhí)行這種操作時(shí),您必須非常用心地注意指定操作的方式,并按某種順序來安排它們,使得操作之間不會互相影響。例如:
$ sed '
/three/ s/three/four/
/two/ s/two/three/' sample_one
one 1
three 1
four 1
one 1
three 1
three 1
four 1
$
這非常有效,因?yàn)?"three" 值在 "two" 變成 "three" 之前得到修改。
標(biāo)簽和注釋
可以在 sed 腳本文件中放置標(biāo)簽,這樣一旦文件變得龐大,可以更容易地說明正在發(fā)生的事情。存在各種各樣與這些標(biāo)簽相關(guān)的命令,它們包括:
接下來的步驟
訪問并收藏 Linux 技術(shù)中心
閱讀 Dale Dougherty 和 Arnold Robbins 的著作 sed awk, 2nd Edition (O'Reilly Associates 出版社)。
: 冒號表示一個(gè)標(biāo)簽名稱。例如:
:HERE
以冒號開始的標(biāo)簽可以由 "b" 和 "t" 命令處理。
b {label} 充當(dāng) "goto" 語句的作用,將處理發(fā)送至前面有一個(gè)冒號的標(biāo)簽。例如,
b HERE
將處理發(fā)送給行
:HERE
如果緊跟 b 之后沒有指定任何標(biāo)簽,則處理轉(zhuǎn)至腳本文件的末尾。
t {label} 只要自上次輸入行或執(zhí)行一次 "t" 命令以來進(jìn)行了替換操作,就轉(zhuǎn)至該標(biāo)簽。和 "b" 一樣,如果沒有給定標(biāo)簽名,則處理轉(zhuǎn)至腳本文件的末尾。
# 符號作為一行的第一個(gè)字符將使整行被當(dāng)作注釋處理。注釋行與標(biāo)簽不同,不能使用 b 或 t 命令來轉(zhuǎn)到注釋行上。