第二十章 文本處理

第二十章 文本處理

所有類UNIX系統都嚴重依賴于文本文件來存儲數據,所以存在大量文本操作工具也在情理之中。

相關命令:

  • cat:拼接文件。
  • sort:排序文本行。
  • uniq:報告或忽略重復的行。
  • cut:從每行中刪除部分內容。
  • paste:合并行。
  • join:連接兩個文件中具有公共字段的行。
  • comm:逐行比較兩個已排序的文件。
  • diff:逐行比較文件。
  • patch:對原文件應用diff文件。
  • tr:轉寫或刪除文件。
  • sed:用于文本過濾和轉換的流編輯器。
  • aspell:交互式拼寫檢查器。

文本的應用

到目前為止,學習過兩種文本編輯器(Nano和Vim),看過多個配置文件,也看到過許多命令的輸出結果,它們都離不開文本。除此之外,文本還應用到很多地方。

文檔

很多人都使用純文本格式編寫文檔。雖然不難看出用小文本文件記錄些簡單的筆記確實有用,但編寫文本格式的大型文檔也是可行的。有一種流行的方式就是先采用文本格式編寫大型文檔,然后在其中嵌入標記語言來描述最終文檔的格式。許多科技論文就是這樣寫出來的。

網頁

世界上流行的電子文檔類型包括網頁了。網頁是使用超文本標記語言(Hypertext Markup Language, HTML)或可擴展標記語言(Extensible Markup Language, XML)來描述文檔可視格式的文本文檔

電子郵件

電子郵件本質上是一種基于文本的媒介。就算是非文本附件,在傳輸的時候也會被轉換為文本格式。郵件消息以標題(header)開頭,描述了該郵件的來源以及其傳輸過程中所進行的處理,然后是郵件消息正文(body)。

打印機輸出

在類UNIX系統中,輸出到打印機的消息是以純文本格式發送的,如果待打印頁面包含圖像,則將其轉換為稱作PostScript的文本格式頁面描述語言的描述信息,然后發送到負責生成待打印圖形點(graphic dots)程序


程序源代碼

類UNIX系統中有不少命令行程序都是為了支持系統管理和軟件開發而編寫的,文本處理程序也不例外,其中有很多是為解決軟件開發問題而設計的。文本處理對軟件開發者重要的原因在于所有的軟件一開始都是文本。軟件開發者實際編寫的程序源代碼始終都是文本格式。


溫故知新

在第6章中,提到了一些除命令行參數之外還能接受標準輸入的命令。不過當時只是"一筆帶過",現在詳細了解這些命令如何進行文本處理。

cat——連接文件并打印

cat命令中,有不少選項可用于增強文本內容的視覺效果。-A就是一個例子,它能夠顯示文本中的非輸出字符。有時想知道可見文本中是否嵌有控制字符。常見的控制字符就是制表符和回車符,后者多見于MS-DOS風格的文本文件的行尾。另一種常見情況是文本文件中包好末尾帶有空格的文本行。

將cat命令作為一個簡單的文本處理器。輸入了一個以制表符開頭,若干空格結尾的文本行。

以默認方式輸出文本:

cat > foo.txt

輸出內容如下:


The quick brown fox jumped over the lazy dog.



使用帶有-A選項的cat顯示文本:

cat -A foo.txt

輸出內容如下:


^IThe quick brown fox jumped over the lazy dog. $



可以看到,文本中的制表符由^I表示。這是一種常見表示法,代表Ctrl-I。還可以看到$出現在真正的行尾,這說明文本中包含結尾空格。

有些cat選項可用于修改文本,其中較突出的兩個分別是-n或-s,前者能夠為文本行加上行號,后者能夠禁止輸出連續的空白行。

例如:


[me@linuxbox ~]$ cat > foo.txt
The quick brown fox

jumped over the lazy dog.
[me@linuxbox ~]$ cat -ns foo.txt
1 The quick brown fox
2
3 Jumped over the lazy dog.


在這個例子中,我們創建了一個新版本的foo.txt測試文件,其中包含被兩個空白分隔的兩行文本。經cat的-ns選項處理之后,多余的空白行被刪除了,剩下的文本行也被加上了行號。雖然這算不上復雜的處理過程,但文本的確經過了處理。

sort-排序

sort對標準輸入內容或命令行上指定的文件進行排序,并將結果發送至標準輸出。

例如:對文件foo.txt進行排序:
foo.txt的內容:


c
a
b


sort foo.txt

輸出結果如下:

a
b
c


從輸出結果可以看出,sort是按字典序對字母進行排序的。

sort可以接受命令行上指定的多個文件作為參數,所以能將多個文件合并成單個文件。
例如:假設有3個文本文件,我們想將其合并成一個有序文件,可以這樣做:

sort file1.txt  file2.txt   file3.txt  > final_sorted_list.txt

常用的sort選項

選項描述
-b, --ignore-leading-blanks在默認情況下,對整行進行排序,從行內的第一個字符開始。該選項使sort忽略每行開頭的空白字符,從第一個非空白字符開始排序
-f, --ignore-case排序時不區分大小寫
-n, --numeric-sort根據字符串的數值(numberic evaluation)排序。該選項使排序按照數值順序,而不按照字母表順序進行
-r, --reverse降序排序。輸出結果按照降序排列
-k, --key=field1[,field2]不再按照整行,而是按照由區間范圍[field1,field2]指定的關鍵字字段進行排序。
-m,–merge每個參數被視為預排序過的文件名稱。將多個文件合并單成單個有序結果,不再執行額外的排序
-o, --output=file將排序后的輸出發送至file,而非標準輸出
-t, --field-separator=char定義字段分隔符。在默認情況下,字段由空格符或制表符分隔

例如:
對數值數據進行排序,需要通過du命令獲取各個目錄的占用磁盤空間,du命令格式如下:

du -s path #統計path下各個字母錄所占用的磁盤空間。

對/usr/share下的子目錄的占用磁盤空間進行降序排序:

du -s /usr/share/* | sort -nr | head 

命令結果如下:

509940 /usr/share/local-langpack
242660 /usr/share/doc
197560 /usr/share/fonts
179144 /usr/share/gnome
146764 /usr/share/myspell
144304 /usr/share/gimp
135880 /usr/share/dict
76508 /usr/share/icons
68072 /usr/share/apps
62844 /usr/share/foomatic



通過-n和-r選項,按照數值進行降序排序,使最大值出現了結果最前面。之所以可行的原因在于數值位于每行的開頭位置。如果像根據行內的某個值來排序。下面是ls -l的輸出結果:

[me@linuxbox ~]$ ls -l /usr/bin | head
total 152948

-rwxr-xr-x 1 root root 34829 2016-04-04 02:42 [
-rwxr-xr-x 1 root root 101556 2007-11-27 06:08 a2p
-rwxr-xr-x 1 root root 13036 2016-02-27 08:22 aconnect
-rwxr-xr-x 1 root root 10552 2007-08-15 10:34 acpi
-rwxr-xr-x 1 root root 3800 2016-04-14 03:51 acpi_fakekey
-rwxr-xr-x 1 root root 7536 2016-04-19 00:19 acpi_listen
-rwxr-xr-x 1 root root 3576 2016-04-29 07:57 addpart
-rwx-xr-x 1 root root 20808 2016-01-03 18:02 addr2line
-rwx-xr-x 1 root root 489704 2016-10-09 17:02 adept_batch



使用sort進行文件大小排序:

[me@linuxbox ~]$ ls -l /usr/bin | sort -nrk 5 | head -n 5

-rwxr-xr-x 1 root root 8234216 2016-04-07 17:42 inkscape
-rwxr-xr-x 1 root root 8222692 2016-04-07 17:42 inkview
-rwxr-xr-x 1 root root 3746508 2016-03-07 23:45 quanta
-rwxr-xr-x 1 root root 3654020 2016-08-26 23:45 gimp-2.4
-rwxr-xr-x 1 root root 2928760 2016-09-10 14:31 gdbtui



sort的許多用法都涉及表格型數據(tabular data)處理,例如上述ls命令的輸出結果。如果套用數據庫的術語,可以稱每行是一條記錄,每列是一個字段,諸如文件屬性、鏈接數、文件名、文件大小等。sort能夠單獨的字段,用數據庫的術語來說,可以指定一個或多個關鍵字段(key fields)作為排序關鍵字(sort keys)。指定了-n和-r選項,按照數值進行降序排序,同時還制定了-k 5,使sort用第5個字段作為排序關鍵字。

-k選項具備不少特征,這些特征值得注意,先介紹sort定義字段的。考慮一個簡單的文本文件,其中只有一行內容,包含作者和姓名:


William Shotts


在默認情況下,sort將該行視為兩個字段。第一個字段包含字符串Willian,第二個字段包含字符串Shotts。

這意味著空白字符(空格符和制表符)被用作字段之間的分隔符,在進行排序時,分隔符包括在字段中。

ls輸出包含8個字段,其中第5個字段是文件大小:


-rwxr-xr-x 1 root root 8234216 2016-04-07 17:42 inkscape


sort允許出現多個-k選項,這樣救就能指定多個排序關鍵字。關鍵字可以是字段范圍。如果沒有指定范圍,則從指定字段開頭,一直延續到行尾。

采用短選項-k 1,1 -k 2n,將排序限制在第一個字段中,所以指定1,1,意思時"從字段1開始,至字段1結束“。第二個-k選項指定了2n,意思是字段2作為排序關鍵字且按照數值進行排序。這些選項字母和sort的全局選項一樣:b(忽略開頭的空白字符)、n(數值排序)、r(降序排序)等。

列表中第3個字段包含的日期格式不適合排序。在計算機中,日期通常采用年-月-日的形式,以便按時間順序進行排序,但這里采用的是月/日/年格式。sort提供了-k選項允許指定字段偏移,這樣就可以指定關鍵字了:

sort -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt

該命令輸出結果如下:


Fedora 10 11/25/2008
Ubuntu 8.10 10/30/2008
SUSE 11.0 06/19/2008
Fedora 9 05/13/2008
Ubuntu 8.04 04/24/2008
Fedora 8 11/08/2007
Ubuntu 7.10 10/18/2007


通過指定-k 3.7, 告知sort排序關鍵字從第3個字段的第7個字符開始(對應于年份)。與此類似,分別指定-k 3.1和 -k 3.4,劃分出日期中的月和日,另外還加入了-n和-r選項來實現數值降序排序。-b選項用于禁止日期字段開頭的空格。

sort提供了 -t選項來定義字符分隔符。
例如:按照第七個字段排序passwd文件,可以這樣做:

sort -t ':' -k 7 /etc/passwd | head

命令輸出如下:


me?1001:1001:Myself,:/home/me:/bin/bash
root?0:0:root:/root:/bin/bash
dhcp?101:102::/nonexistent:/bin/false
gdm?106:114:Gnome Display Manager:/var/lib/gdm:/bin/false
hplip?104:7:HPLIP system user,:/var/run/hplip:/bin/false
klog?103:104::/home/klog:/bin/false
messagebus?108:119::/var/run/dbus:/bin/false
polkituser?110:122:PolicyKit,:/var/run/PolicyKit:/bin/false
pulse?107:116:PulseAudio daemon,:/var/run/pulse:/bin/false



將冒號指定為字段分隔符。

uniq-刪除重復行

uniq執行的任務較簡單,即指定一個排序過的文件,它會刪除其中所有重復的行并將結果發送至標準輸出。uniq經常配合sort來清楚重復輸出。

命令如下:

uniq filename #去重 filename內容中的相同的行寫到標準輸出sort filename | uniq #對排序后的filename的內容去重寫到標準輸出


盡管uniq屬于傳統的UNIX工具,多與sort配合使用,而GNU版本的sort支持-u選項,同樣能夠刪除有序輸出中的重復行


例如對文件foo.txt進行去重

sort foo.txt | uniq

foo.txt文件內容:


a
b
c
a
b
c


命令輸出結果如下:


a
b
c


從結果可以看出uniq可以去重,但是要注意uniq只能刪除連續的重復行因此需要通過sort進行排序后調用uniq


常用uniq選項
選項描述
-c, --count輸出重復的行,在其之前加上改行重復出現的次數
-d, --repeated只輸出重復的行,不包括非重復行
-f n, --skip-fields=n忽略每行前n個字段。和sort一樣,字段以空白字符分隔;但不同于sort,uniq沒有能夠設置其它字段分隔符的選項
-i, --ignore-case對比內容的時候忽略大小寫敏感
-s n, --skip-chars=n跳過(忽略)每行開始的前n個字符
-u,–unique只輸出不重復的行。忽略重復行

例如: 使用-c選項報告文件foo.txt中重復行的數量

命令如下:

sort foo.txt | uniq -c

命令輸出結果如下:


2 a
2 b
2 c



切片和切塊

接下來的命令可用于從文件中提取文本列,再以其它方式重新組合。

cut-從每行中刪除部分內容

cut能夠從每行提取部分文本并將其輸出至標準輸出。

常用的cut選項

選項描述
-c list, --characters=list提取由list定義的部分行。list可以是一個或多個逗號分隔的數值范圍
-f list, --fields=list從行中提取由list定義的一個或多個字段。list可以包含一個或多個字段,抑或是逗號分隔字段范圍
-d delim, --delimiter=delim如果制定了-f,則使用delim作為字段分隔符。在默認情況下,字段必須單個制表符分隔
–complement提取除-c或-f指定部分之外的文本行

cut適合從其他程序產生的文件中提取文本,而不是從用戶輸入中直接提取。

例如:利用-f選項提取由制表符分隔的第3個字段.。

用cat -A查看distros.txt文件內容:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

可以看出字段間分隔符號為制表符。

使用-f選項提取字段:

cut -f 3 distros.txt

命令結果如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

由于文件采用制表符作為分隔符,因此最好使用cut提取自字段而不是字符。

在上個例子中,提取的字段包含相同長度的數據,因此可以通過提取每行中的年份來提取字符:

命令如下:

cut -f 3 distros.txt | cut -c 7-10

命令結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

再次對distros.txt執行cut,就可以提取7-10個字符,對應于日期中的年份。

在處理字段時,可以指定不同的字段分隔符。例如從/etc/passwd文件中提取第一個字段:

cut -d ':' -f 1 /etc/passwd | head

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

本例中,/etc/passwd以冒號分隔字段,cut通過-d選項指定冒號作為分隔符,通過-f選項指定第一個字段。

paste-合并行

paste將文本添加列添加到文件中。通過讀取多個,然后將每個文件中的字段合并來實現的。

格式如下:

paste file1 file2 ... #按照順序將file1,file2等文件的內容橫向排列

例如:將發行日期放在發行版本名詞之前,

先基于distros.txt生成幾個文件:

sort -k 3.7nbr -k 3.1nbr -k 3.4nbr distros.txt > distros-by-date.txtcut -f 1,2 distros-by-date.txt > distros-versions.txtcut -f 3 distros-by-date.txt > distros-dates.txt

其內容如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


使用paste將發行日期放在發行版本名詞之前,形成按照順序排列的發行清單:
paste distros-dates.txt distros-versions.txt

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


join-連接兩個文件中具有公共字段的行

在某些方面join和paste一樣,將文本列添加到文件中,只不過前者采用了一種獨特的方式。連接(join)操作常見于關系數據庫,用于將多個數據表中具有共享關鍵字字段(shared key field)的數據合并在一起,形成所需的結果。join命令根據關鍵字連接多個文件的數據。

例如通過join命令將發行日期放在發行版本之前:

首先生成幾個文件:

cut -f 1,1 distros-by-date.txt > distros-names.txtpaste distros-dates.txt distros-names.txt > distros-key-names.txtcut -f 2,2 distros-by-date.txt > distros-vernums.txt
paste distros-dates.txt distros-vernums.txt > distros-key-vernums.txt

文件內容如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


現在有了兩個具有共享關鍵字的文件。要指出的重要一點是文件必須依據關鍵字段排序,這樣join才能正常工作:
join distros-key-vernums.txt distros-key-names.txt | head

輸出結果如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

默認情況下,join使用空白字符作為輸入字段分隔符,單個空格符作為輸出字段分隔符。可以指定相關選項修改規則,詳見join手冊頁。

比較文本

比較文本文件的不同版本。對系統管理員和軟件開發者而言,尤其重要。

comm-逐行比較兩個已排序的文件

comm命令比較兩個文本文件,顯示各自獨有的行和共有的行。

命令如下:

comm file1 file2 #逐行比較file1和file2,其輸出結果第一列是file1獨有的行,第二列是file2獨有的行,第三列是file1和file2共有的行

例如:比較file1.txt和file2.txt文件

file1.txt的文件內容:


a
b
c
d



file2.txt的文件內容

b
c
d
e



使用comm比較這兩個文件:
comm file1.txt file2.txt

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

可以看出a是file1獨有的內容,e是
file2獨有的內容,b,c,d是file1和file2共有的內容。

comm還支持-n選項,其中,n可以是1、2或3。在使用時,該選項制定了要禁止顯示那些列。
例如:只顯示兩個文件共有的行,可以禁止輸出第一列和第二列:

comm  -12 file1.txt file2.txt

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


diff-逐行比較文件

diff可用于檢測文件之間的差異。支持多種輸出形式,能夠一次處理大量文本文件。軟件開發人員經常diff檢測不同版本的源代碼之間的差異,進而遞歸檢查整個源代碼目錄(通常稱為源代碼樹)。diff的常見用法是創建diff文件或補丁,共patch等其他程序使用。

使用diff查看上一個例子中的文件:

diff file1.txt file2.txt

命令輸出如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

其輸出格式只簡要描述了兩個文件之間的差異。在默認格式中,每組變動之前都會有一個形如"范圍 操作 范圍” (range operation range)的變動命令(change command),它用于描繪將第一個文件轉換為第二個文件所需的位置和變動類型。

diff的變動命令

命令描述
r1ar2將第二個文件中位于r2處的行追加到第一個文件中的r1處
r1cr2將第一個文件中位于r1處的行修改(替換)為第二個文件中位于r2處的行
r1dr2刪除第一個文件中位于r1處的行,該行也出現在第二個文件中r2處

這種格式中,范圍是由逗號分隔的開頭行和終止行組成的。作為默認格式(主要是為了POSIX合規性以及向后兼容傳統的UNIX版本的diff),它并沒有另外幾種可選格式應用得那么廣泛。上下文格式(context format)和合并格式(unified format)是兩種更為流行的格式。

上下文格式(-c選項)如下所示:

diff -c file1.txt file2.txt

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


輸出結果以兩個文件的名稱及其時間戳作為開頭。第一個文件用星號標記,第二個文件用連字符標記。在剩下的輸出結果中這兩種標記分別代表對應的文件。接下來,會看到若干組變動,其中包括上下文行號。第一組中:

*** 1, 4 ***



表明第一個文件中的第1行到第4行。隨后會看到:


— 1, 4 —


表明第二個文件中的第1行到第4行。


diff上下文格式的變動指示符

指示符含義
上下文行。并不表示兩個文件之間的差異
-要刪除的行。該行出現在第一個文件,但不出現在第二個文件中
+要添加的行。該行出現在第二個文件,但不出現在第一個文件中
要改動的行。該行的兩個版本都會顯示,各自出現在變動組相應的區域中

合并格式和上下文格式類似,但更簡明。該格式由-u選項指定。

命令如下:

diff -u file1.txt file2.txt

命令輸出如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

上下文格式和合并格式之間較明顯的區別在于后者去除了重復的上下文行,使合并格式的輸出結果比上下文格式更為精簡。可以看到和上下文格式一樣的時間戳,后面緊跟著字符串@@-1,4 +1,4 @@。指明了變動組內第一個文件中的行和第二個文件中的行。接下來便是各行本身以及默認的3行上下文。

diff合并格式的變動指示符

指示符含義
該行為兩個文件所共有
-該行要從第一個文件中刪除
+該行要加入第一個文件

patch-對原文件應用diff文件

patch命令能夠對文本文件應用改動。它接受diff輸出,一般用于將舊版本的文件轉換為新版本。例如Linux內核是由一支規模龐大、組合松散的貢獻者團隊開發的,他們持續不斷地向源代碼提交細小的改動。如果某個開發人員做一次改動,就要向每位開發人員發送整個內核源代碼樹,這種做法并不切實際。實際上只要發送diff文件就夠了。diff文件包含了內核新、舊版本之間的改動內容。接受者只需使用patch命令將這些改動應用于自己的內核源代碼即可。diff/patch提供了兩個重要優勢。

  • 相較于整個源代碼樹,diff文件要小得多。
  • diff文件簡潔地描述了所做的改動,便于查閱人員快速地對該文件做出評估。

diff/patch能夠處理任何文本文件,并不局限于源代碼。二者同樣適用于配置文件或其他文件。

為了生成可供patch使用的diff文件,GNU文檔建議按照下列方式使用diff:


diff -Naur old_file new_file > diff_file


其中,old_diff和new_diff可以是單個文件,也可以是包含多個文件的目錄。-r選項能夠對目錄樹執行遞歸操作。

只要生成了diff文件,就可以將diff應用于舊文件,使其成為新版本的文件:


patch < diff_file


例如將fiel1.txt的內容更改為file2.txt的內容:

生成diff_file文件:

diff -Naur file1.txt file2.txt > patchfile.txt

使用patch通過patchfile.txt文件將file1.txt的內容更新為file2.txt的內容。
patch < pachfile.txt

命令輸出結果如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


查看更改后的file1.txt的內容:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


即時編輯

文本編輯器大多是交互的,也就是需要移動光標的,然后輸入內容,還有非交互的文本編輯方式。

tr-轉寫或刪除字符

tr命令可用于轉寫(transliterate)字符。可以將其視為某種基于字符的“搜索-替換”操作。轉寫是將字母表中的一個字母更改為另一個字母的過程。

命令格式如下:

tr    target #

tr接受兩個參數:源字符集合和目標字符集合。有3種方法表示字符集合:

  • 枚舉列表,例如ABCDEFGHIJKLMNOPQRSTUVWXYZ。
  • 字符范圍,例如A-Z。
  • POSIX字符集,例如[:upper:]。

例如將多個字符轉換為單個字符:

echo "lowercase letters" | tr [:lower:] A

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


除了轉寫,將MS-DOS文本轉換為UNIX文本的問題,這需要刪除每行行尾的回車符。可以通過tr命令來實現:
tr -d '\r' < dos_file > unix_file

其中dos_file是要被轉換的文件,unix_file是轉換后的結果。這種命令形式使用了轉義字符\r來表示回車符。

tr可以使用-s選項能夠"擠壓"(刪除)重復出現的字符。例如:

echo "aaabbbccc" | tr -s ab

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

注意重復字符必須是連續的,如果不是連續的,則不會有擠壓效果:

echo "abcabcabc" | tr -s ab

命令輸出結果如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

可以看出并沒有產生擠壓。

sed-用于文本過濾和轉換的流編輯器

sed是流編輯器(stream editor)的簡稱。它可以對文本流(一組指定的文件或標準輸入)進行編輯。sed功能強大且比較復雜。

sed的工作方式:為其指定單個編輯命令(在命令行中)或者包含多個命令的腳本文件名,然后對文本流中的每行文本執行這些命令。下面是一個示例:

echo "front" | set 's/front/back/'

命令輸出結果如下:

back



從結果可以看出這是個查找-替換操作,將front替換為back,在set的參數中s是編輯命令,front和back是s的參數,front是查找的字符串,back是替換的字符串。

可以給sed命令之前可以添加一個地址,用于指定要編輯輸入流中的那些行。
例如:


[me@linuxbox ~]$ echo “front” | sed ‘1s/front/back/’
back
[me@linuxbox ~]$ echo “front” | sed ‘2s/front/back/’


第一條命令指定對第一行操作,因為輸入為front,所以輸出back。第二條命令無輸出,是因為對第二行進行操作,但輸入只有一行,故沒有輸出。

sed地址方式表示

地址描述
n行號,其中n為正整數
$最后一行
/regexp/匹配POSIX BRE的行。注意,正則表達式由正斜線分隔。正則表達式也可以選擇使用其他字符分隔,這需要使用\cregxpc來指定正則表達式,其中的c就是分隔符
addr1,addr2從addr1至addr2的行范圍(包括addr1和addr2)。地址可以是前面所述的任何一種地址形式
first~step匹配從行號first開始,然后間隔依次為step的那些行。例如1~2指代所有奇數行,5~5指代第5行和之后所有是5倍數的行
addr1,+n匹配addr1和接下來的n行
addr!匹配除addr之所有行,addr可以是前面所述的任何一種地址形式

演示各種地址表示方式。來看地址范圍:

sed -n '1,5p' distros.txt

輸出結果如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

本例中,輸出范圍從第1行~第5行。因此用到了p命令,改名令只是簡單的輸出匹配行。還必須加入-n(no auto-print選項)選項,使sed不默認輸出所有行。

使用正則表達式:

sed -n '/SUSE/p' distros.txt

輸出命令如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

通過加入正斜線分隔的正則表達式/SUSE/,就能類似于grep那樣的方法提取出匹配的行。

最后在地址加入!,嘗試排除操作:

sed -n '/SUSE/!p' distros.txt

命令輸出結果如下:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

至此介紹了兩個sed編輯命令s和p。

sed基本編輯命令

命令描述
=輸出當其行行號
a將文本追加到前行之后
d刪除當前行
i將文本插入當前行之前
p輸出當前行。在默認情況下,sed會輸出所有行,只編輯文件中匹配指定地址的那些行。通過-n選項,可以拒絕該默認行為
q退出sed,不再處理剩余的。如果未指定-n選項,會輸出當前行
Q退出sed,不再處理剩余的行
s/regexp/replacement/將regexp匹配的地方替換成replacement。replacement可以包含特殊字符&,其代表regexp所匹配到的文本。除此之外,replacement也可以包含序列\1~\9,其代表regexp中對應的子表達式所匹配到的文本。在后文討論向后引用的時候,會更詳細地說明。在replacement之后的結尾正斜線處,可以指定一些能夠改變s命令行為的可選標志
y/set1/set2通過將set1中的字符更換成set2中對應的字符來執行轉寫。注意,和tr不同的是,sed要求set1和set2這兩個字符集合的長度必須相同

盡管日期經過了格式化,但如果采用年-月-日的格式會更好(便于排序)。通過sed命令可以實現,其命令如下:

sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' distros.txt

命令輸出如下:
外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳


sed命令的基本結構如下:


sed ‘s/regexp/replacement/’ distros.txt



因為日期采用的格式為月/日/年且出現在行尾,所以可以這樣寫:

[0-9]{2}/[0-9]{2}/[0-9]{4}$


該正則表達式匹配2個數位、1個斜線、2個數為、1個斜線、4個數位。regexp部分搞定。

在一些使用了ERE的應用中,包含“向后引用”特征,工作方式是這樣的:如果\n出現在replacement中,這里的n是1~9中的一個數字,則此序列指代的是之前的正則表達式中對應的子表達式匹配到內容。只用將需要部分放入括號中即可:


([0-9]{2})/([0-9]{2})/([0-9]{4})$



現在得到3個子表達式。第一個包含月份,第2個包含月份中的天數,第三個包含年份。可以構建出下列replacement:

\3-\1-\2


這樣就得到了年份、連字符、月份、連字符、天數。

于是整個命令如下:


set -n ‘s/([0-9]{2})/([0-9]{2})/([0-9]{4})$/\3-\1-\2/’



由于sed默認只接受BRE,因此正則表達式中一些本作為元字符的字符會被當作文字字符。解決辦法是使用反斜線轉義會出問題的字符:

set -n ‘s/([0-9]{2})/([0-9]{2})/([0-9]{4})$/\3-\1-\2/’ distros.txt


aspell-交互式拼寫檢查器

aspell多為需要拼寫檢查功能的程序所用,但也可以作為獨立的命令行工具發揮效用。它能夠智能地檢查各種文本文件,其中包括HTML文檔、C/C++程序、電子郵件等。

命令格式如下:


aspell check textfile


例如檢查普通的文本文件:
foo.txt的文件內容:


The quick brown fox jimped over the laxy dog.


aspell check foo.txt

會提示jimped拼寫錯誤,會被高亮顯示,由于本人操作系統不支持英文拼寫檢查故不能進行測試。

對于HTML標簽內容拼寫有誤,加入檢查模式選項-H(HTML)就能解決這個問題:

aspell -H check foo.txt

不能測試原因同上。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83230.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83230.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83230.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Reactor 和 Preactor

Reactor 和 Preactor 是兩個在工業控制、生產調度和事件驅動系統中非常重要的設計模式或框架&#xff0c;不少人會用這兩個名詞來描述不同的編程思想或技術架構。 一、Reactor 模式&#xff08;反應器模式&#xff09; 1. 概述 Reactor 模式其實是一種I/O事件通知的設計思想…

siglip2(2) Naflex模型的動態分辨率原理

動態分辨率的圖片縮放行為 操作辦法: 操作1。修改preprocessor_config.json,設置"max_num_patches": 256,可從256(1616)改為196(1414)。 操作2。在預處理圖片時,可按照如下方式傳入參數max_num_patches。 inputs = self.processor(images=videos, **{"ima…

??技術深度解析:《鴻蒙5.0+:無感續航的智能魔法》?

??引言&#xff1a;從“充電焦慮”到“無感續航”?? ??用戶痛點??&#xff1a; 刷短視頻時電量暴跌、夜間待機掉電快、多設備切換耗電失控——傳統系統無法平衡性能與功耗。??鴻蒙5.0突破??&#xff1a; 通過??方舟引擎3.0??&#xff08;編譯級能效優化&#…

振動力學的三類基本問題

振動問題的分類依賴于分類的出發點&#xff0c;本文從系統論的角度來分析振動問題的分類。如圖1&#xff0c;一個振動系統&#xff0c;包括三個方面&#xff1a;輸入、系統特性&#xff08;或稱為系統模型&#xff09;、輸出。其中&#xff0c;輸入指外界載荷&#xff0c;包括力…

過濾攻擊-聚合數據

公開的聚合數據是通過對原始細粒度數據進行匯總、統計或轉換后發布的&#xff0c;旨在提供群體層面的洞察而非個體信息。它們具有以下關鍵特征&#xff1a; 1. 去標識性&#xff08;De-identification&#xff09; 表現&#xff1a; 直接標識符&#xff08;姓名、身份證號、手機…

小紅書 發評論 分析 x-s x-t

聲明: 本文章中所有內容僅供學習交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包內容、敏感網址、數據接口等均已做脫敏處理&#xff0c;嚴禁用于商業用途和非法用途&#xff0c;否則由此產生的一切后果均與作者無關&#xff01; 逆向過程 部分Python代碼 ck jso…

pycharm找不到高版本conda問題

pycharm找不到高版本conda問題 高版本的condaPycharm不能自動識別&#xff0c;需要手動添加。 首先打開你要添加的conda環境win的話在conda終端輸入 where conda查找conda的可執行文件位置 進入Pycharm設置&#xff0c;點擊添加解釋器&#xff0c;點擊加載環境&#xff0c;…

C56-親自實現字符串拷貝函數

一 strcpy簡介 功能&#xff1a;將源字符串&#xff08;包括 \0&#xff09;復制到目標地址。 原型&#xff1a; char *strcpy(char *dest, const char *src);參數&#xff1a; dest&#xff1a;目標地址&#xff08;需足夠大&#xff09;。src&#xff1a;源字符串&#xf…

設計模式——適配器設計模式(結構型)

摘要 本文詳細介紹了適配器設計模式&#xff0c;包括其定義、核心思想、角色、結構、實現方式、適用場景及實戰示例。適配器模式是一種結構型設計模式&#xff0c;通過將一個類的接口轉換成客戶端期望的另一個接口&#xff0c;解決接口不兼容問題&#xff0c;提高系統靈活性和…

java 開發中 nps的內網穿透 再git 遠程訪問 以及第三放支付接口本地調試中的作用

在Java開發中&#xff0c;NPS內網穿透、Git遠程訪問和第三方支付接口的本地調試結合使用&#xff0c;可以有效提升開發效率和調試能力。以下是它們的具體作用及協作場景&#xff1a; 第一&#xff1a;為什么需要nps內網穿透 1. NPS內網穿透的作用 NPS&#xff08;內網穿透工具…

換ip是換網絡的意思嗎?怎么換ip地址

在數字化時代&#xff0c;IP地址作為我們在網絡世界的"身份證"&#xff0c;其重要性不言而喻。許多人常將"換IP"與"換網絡"混為一談&#xff0c;實際上兩者雖有聯系卻存在本質區別。本文將澄清這一概念誤區&#xff0c;并詳細介紹多種更換IP地址…

云游戲混合架構

云游戲混合架構通過整合本地計算資源與云端能力&#xff0c;形成了靈活且高性能的技術體系&#xff0c;其核心架構及技術特征可概括如下&#xff1a; 一、混合架構的典型模式 分層混合模式? 前端應用部署于公有云&#xff08;如渲染流化服務&#xff09;&#xff0c;后端邏輯…

Docker常用命令操作指南(一)

Docker常用命令操作指南-1 一、Docker鏡像相關命令1.1 搜索鏡像&#xff08;docker search&#xff09;1.2 拉取鏡像&#xff08;docker pull&#xff09;1.3 查看本地鏡像&#xff08;docker images&#xff09;1.4 刪除鏡像&#xff08;docker rmi&#xff09; 二、Docker容器…

軟件性能之CPU

性能是個宏大而駁雜話題&#xff0c;從代碼&#xff0c;到網絡&#xff0c;到實施&#xff0c;方方面面都會涉及到性能問題&#xff0c;網上對性能講解的文章多如牛毛&#xff0c;從原理到方法再到工具都有詳細的介紹&#xff0c;本文雖不能免俗&#xff0c;但期望能從另外一個…

[SC]SystemC在CPU/GPU驗證中的應用(三)

SystemC在CPU/GPU驗證中的應用(三) 摘要:下面分享50個逐步升級SystemC編程能力的示例及建議的學習路線圖。您可以一次一批地完成它們——從前五個基礎的例子開始,然后轉向channels, TLM, bus models, simple CPU/GPU kernels等等。在每個階段掌握之后,再進行下一組…

如何設計高效的數據湖架構:存儲策略、Schema 演進與數據生命周期管理

本文圍繞現代數據湖架構的核心設計理念與實踐展開,重點討論如何高效組織數據存儲、支持 Schema 演進與版本管理、實現冷熱數據分層存儲和生命周期治理,確保數據湖在性能、成本、演進和治理能力上的全面可控。 ?? 一、數據湖架構演進概覽 傳統數據倉庫面對高頻更新、Schema…

建筑兔零基礎人工智能自學記錄101|Transformer(1)-14

Transformer 谷歌提出&#xff0c;一組編碼-解碼器 可以同時處理&#xff0c;通過位置編碼來處理單詞 實質是token詞語接龍&#xff08;只是有不同的概率&#xff09; token對應向量 Transformer簡述 文生圖就需要用到transformer黑箱 token 內部層次 中間主要是embedding…

Unity基礎學習(十二)Unity 物理系統之范圍檢測

目錄 一、關于范圍檢測的主要API&#xff1a; 1. 盒狀范圍檢測 Physics.OverlapBox 2. 球形范圍檢測 Physics.OverlapSphere 3. 膠囊范圍檢測 Physics.OverlapCapsule 4. 盒狀檢測 NonAlloc 版 5. 球形檢測 NonAlloc 版 6. 膠囊檢測 NonAlloc 版 二、關于API中的兩個重…

構建安全高效的郵件網關ngx_mail_ssl_module

一、快速上手&#xff1a;最小配置示例 worker_processes auto;mail {server {# 監聽 IMAP over TLSlisten 993 ssl;protocol imap;# TLS 協議與密碼套件ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers HIGH:!aNULL:!MD5;# 證書與私鑰ssl_…

打卡day41

知識回顧 數據增強卷積神經網絡定義的寫法batch歸一化&#xff1a;調整一個批次的分布&#xff0c;常用與圖像數據特征圖&#xff1a;只有卷積操作輸出的才叫特征圖調度器&#xff1a;直接修改基礎學習率 卷積操作常見流程如下&#xff1a; 1. 輸入 → 卷積層 → Batch歸一化層…