17.文本處理(快樂的Linux命令行).

1.本節要學的命令(這章有點長,有點難)

paste

添加一個或多個文本列到文件中,而不是從文件中抽取文本列。

join

join 類似於 paste,它會往文件中添加列,大門時有自己獨特方法.

comm

比較兩個文本文件,顯示每個文件特有的文本行和共有的文把行。

diff

類似於 comm 程序,diff 程序被用來監測文件之間的差異。

patch

把更改應用到文本文件中。

tr

更改字符,我們可以把它看作是一種基於字符的查找和替換操作。
 sed 它對文本流,即一系列指定的文件或標準輸入進行編輯。

aspell

交互式的拼寫檢查器

2.小知識

知識點1:sort命令參數列表?

選項 長選項 描述
-b --ignore-leading-blanks 忽略每行開頭的空格,從第一個非空白字符開始排序。
-f --ignore-case 讓排序不區分大小寫。
-n --numeric-sort 基於字符串的數值來排序。使用此選項允許根據數字值執行排序,而不是字母值。
-r --reverse 按相反順序排序。結果按照降序排列,而不是升序。
-k --key=field1[,field2] 對從 field1到 field2之間的字符排序,而不是整個文本行。
-m --merge 每個參數看作一個預先排好序的文件。把多個文件合併成一個排好序的文件,而沒有執行額外的排序。
-o --output=file 把排好序的輸出結果發送到文件,而不是標準輸出。
-t --field-separator=char 定義域分隔字符。默認情況下,域由空格或製表符分隔。

知識點2:uniq爲什麼刪除不了重複?

答:因爲uniq只能刪除相鄰重複選項,所以源文件必須是排好序的。

知識點3:uniq常見的的選項參數?

選項 說明
-c 輸出所有的重複行,並且每行開頭顯示重複的次數
-d 只輸出重複行,而不是特有的文本行。
-f n 忽略每行開頭的 n 個字段,字段之間由空格分隔,正如 sort 程序中的空格分隔符;
-i 在比較文本行的時候忽略大小寫
-s n 跳過(忽略)每行開頭的 n 個字符。
-u 只輸出獨有的文本行。這是默認的。

知識點4:cut常見的選項參數?

選項 說明
-c char_list 從文本行中抽取由 char_list 定義的文本。這個列表可能由一個或多個逗號 分隔開的數值區間組成。
-f field_list 從文本行中抽取一個或多個由field_list定義的字段。這個列表可能包括一個或多個字段,或由逗號分隔開的字段區間。
-d delim_char 當指定-f 選項之後,使用 delim_char 做爲字段分隔符。默認情況下, 字段之間必須由單個 tab 字符分隔開。
--complement 抽取整個文本行,除了那些由-c 和/或-f 選項指定的文本。

知識點5:diff的更改命令有哪些?

改變 說明
r1ar2 把第二個文件中位置 r2 處的文件行添加到第一個文件中的 r1 處。
r1cr2 用第二個文件中位置 r2 處的文本行更改(替代)位置 r1 處的文本行。
r1dr2 刪除第一個文件中位置 r1 處的文本行,這些文本行將會出現在第二個文件中位置 r2 處。

知識點6:diff的上下文更改指示符?

指示符 意思
blank 上下文顯示行。它並不表示兩個文件之間的差異。
- 刪除行。這一行將會出現在第一個文件中,而不是第二個文件內。
+ 添加行。這一行將會出現在第二個文件內,而不是第一個文件中。
! 更改行。將會顯示某個文本行的兩個版本,每個版本會出現在更改組的各自部分。

知識點7:sed地址表示法?

n 行號,n 是一個正整數。
$ 最後一行
/regexp/ 所有匹配一個 POSIX 基本正則表達式的文本行。注意正則表達式通過 斜槓字符界定。選擇性地,這個正則表達式可能由一個備用字符界定,通過\cregexpc 來 指定表達式,這裏 c 就是一個備用的字符。
addr1,addr2 從 addr1 到 addr2 範圍內的文本行,包含地址 addr2 在內。地址可能是上述任意 單獨的地址形式。
first~step 匹配由數字 first 代表的文本行,然後隨後的每個在 step 間隔處的文本行。例如 1~2 是指每個位於奇數行號的文本行,5~5 則指第五行和之後每五行位置的文本行。
addr1,+n 匹配地址 addr1 和隨後的 n 個文本行。
addr! 匹配所有的文本行,除了 addr 之外,addr 可能是上述任意的地址形式。

知識點8:sed基本編輯命令

命令 說明
= 輸出當前的行號。
a 在當前行之後追加文本。
d 刪除當前行。
i 在當前行之前插入文本。
p 打印當前行。默認情況下,sed 程序打印每一行,並且只是編輯文件中匹配 指定地址的文本行。通過指定-n 選項,這個默認的行爲能夠被忽略。
q 退出 sed,不再處理更多的文本行。如果不指定-n 選項,輸出當前行。
Q 退出 sed,不再處理更多的文本行。
s/regexp/replacement/ 只要找到一個 regexp 匹配項,就替換爲 replacement 的內容。 replacement 可能包括特殊字符 &,其等價於由 regexp 匹配的文本。另外, replacement 可能包含序列 \1到 \9,其是 regexp 中相對應的子表達式的內容。更多信息,查看 下面 back references 部分的討論。在 replacement 末尾的斜槓之後,可以指定一個 可選的標誌,來修改 s 命令的行爲。
y/set1/set2 執行字符轉寫操作,通過把 set1 中的字符轉變爲相對應的 set2 中的字符。 注意不同於 tr 程序,sed 要求兩個字符集合具有相同的長度。

知識點9:什麼是正則表達式的逆參照 ?

答:如果序列 \n 出現在 replacement 中 ,這裏 n 是指從 1 到 9 的數字,則這個序列指的是在前面正則表達式中相對應的子表達式。

3.代碼實操

[me@linuxbox ~]$ cat > foo.txt
    The quick brown fox jumped over the lazy dog.  
[me@linuxbox ~]$ cat -A foo.txt
^IThe quick brown fox jumped over the lazy dog.$   
注^I是tab,$是包含末尾的空格。

[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.
注意:-s是禁止輸入多個空白行。

[me@linuxbox ~]$ sort > foo.txt
c
b
a
[me@linuxbox ~]$ cat foo.txt
a
b
c

[me@linuxbox ~]$ du -s /usr/share/* | sort -nr | head
509940         /usr/share/locale-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
注:du 用來表示最大的磁盤空間用戶

[me@linuxbox ~]$ du -s /usr/share/* | sort -nr | head
509940         /usr/share/locale-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

[me@linuxbox ~]$ ls -l /usr/bin | sort -nr -k 5 | head
-rwxr-xr-x 1 root   root   8234216  2008-04-0717:42 inkscape
-rwxr-xr-x 1 root   root   8222692  2008-04-07 17:42 inkview
62844          /usr/share/foomatic
注:基於文件行中的某個數值排序,-k 5 就是基於第五個進行排序,也就是數字那一列。

[me@linuxbox ~]$ sort --key=1,1 --key=2n distros.txt
Fedora         5     03/20/2006
Fedora         6     10/24/2006
Fedora         7     05/31/2007
注:--key=1,1就是對第一個字段進行排序。而--key=2n是這裏面的第二行。

[me@linuxbox ~]$ 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
注:-k 3.7就是第3個字段的第七個字符。而nbr就是-n,-b,-r參數

[me@linuxbox ~]$ sort -t ':' -k 7 /etc/passwd | head
me:x:1001:1001:Myself,,,:/home/me:/bin/bash
root:x:0:0:root:/root:/bin/bash
dhcp:x:101:102::/nonexistent:/bin/false
gdm:x:106:114:Gnome Display Manager:/var/lib/gdm:/bin/false
hplip:x:104:7:HPLIP system user,,,:/var/run/hplip:/bin/false
klog:x:103:104::/home/klog:/bin/false
messagebus:x:108:119::/var/run/dbus:/bin/false

[me@linuxbox ~]$ cat > foo.txt
a
b
c
a
b
c
[me@linuxbox ~]$ uniq foo.txt
a
b
c
a
b
c

[me@linuxbox ~]$ sort foo.txt | uniq -c
        2 a
        2 b
        2 c

[me@linuxbox ~]$ cat -A distros.txt
SUSE^I10.2^I12/07/2006$
Fedora^I10^I11/25/2008$
SUSE^I11.0^I06/19/2008$
Ubuntu^I8.04^I04/24/2008$
Fedora^I8^I11/08/2007$
[me@linuxbox ~]$ cut -f 3 distros.txt
12/07/2006
11/25/2008
06/19/2008
04/24/2008
注:-f 3 抽取第三個字段

[me@linuxbox ~]$ expand distros.txt | cut -c 23-
注:通過expand來處理 distros.txt 文件,再使用 cut 命令,來抽取從位置 23 開始到行尾的每一個字符

[me@linuxbox ~]$ cut -d ':' -f 1 /etc/passwd | head
root
daemon
bin

[me@linuxbox ~]$ cut -f 1,2 distros-by-date.txt > distros-versions.txt
[me@linuxbox ~]$ head distros-versions.txt
Fedora     10
Ubuntu     8.10
SUSE       11.0
[me@linuxbox ~]$ cut -f 3 distros-by-date.txt > distros-dates.txt
[me@linuxbox ~]$ head distros-dates.txt
11/25/2008
10/30/2008
06/19/2008
[me@linuxbox ~]$ paste distros-dates.txt distros-versions.txt
11/25/2008	Fedora     10
10/30/2008	Ubuntu     8.10
06/19/2008	SUSE       11.0
注:paster將兩個文件字段合併爲一個文件


CUSTNUM	    FNAME       ME
========    =====       ======
4681934	    John        Smith

ORDERNUM        CUSTNUM     QUAN ITEM
========        =======     ==== ====
3014953305      4681934     1    Blue Widget

[me@linuxbox ~]$ cut -f 1,1 distros-by-date.txt > distros-names.txt
[me@linuxbox ~]$ paste distros-dates.txt distros-names.txt > distros-key-names.txt
[me@linuxbox ~]$ head distros-key-names.txt
11/25/2008 Fedora
10/30/2008 Ubuntu
06/19/2008 SUSE
[me@linuxbox ~]$ cut -f 2,2 distros-by-date.txt > distros-vernums.txt
[me@linuxbox ~]$ paste distros-dates.txt distros-vernums.txt > distros-key-vernums.txt
[me@linuxbox ~]$ head distros-key-vernums.txt
11/25/2008 10
10/30/2008 8.10
06/19/2008 11.0
[me@linuxbox ~]$ join distros-key-names.txt distros-key-vernums.txt | head
11/25/2008 Fedora 10
10/30/2008 Ubuntu 8.10
06/19/2008 SUSE 11.0

[me@linuxbox ~]$ cat > file1.txt
a
b
c
d
[me@linuxbox ~]$ cat > file2.txt
b
c
d
e
[me@linuxbox ~]$ comm file1.txt file2.txt
a
        b
        c
        d
    e
注:第一列是第一個文件特有的,第二列是第二個文件所有的。第三列是共有的。

[me@linuxbox ~]$ comm -12 file1.txt file2.txt
b
c
d
注:-12是隱藏第一列和第二列的意思。

[me@linuxbox ~]$ diff file1.txt file2.txt
1d0
< a
4a4
> e
注:

[me@linuxbox ~]$ diff -c file1.txt file2.txt
*** file1.txt    2008-12-23 06:40:13.000000000 -0500
--- file2.txt   2008-12-23 06:40:34.000000000 -0500
***************
*** 1,4 ****
- a
  b
  c
  d
--- 1,4 ----
  b
  c
  d
  + e
注:-c就是上下文模式,這個輸出結果以兩個文件名和它們的時間戳開頭。第一個文件用星號做標記,第二個
文件用短橫線做標記。
*** 1,4 **** 其表示第一個文件中從第一行到第四行的文本行。
--- 1,4 ---- 其表示第二個文件中從第一行到第四行的文本行。
-a bcd +e 還是比較好理解的

[me@linuxbox ~]$ diff -u file1.txt file2.txt
--- file1.txt 2008-12-23 06:40:13.000000000 -0500
+++ file2.txt 2008-12-23 06:40:34.000000000 -0500
@@ -1,4 +1,4 @@
-a
 b
 c
 d
+e
注:@ -1,4 +1,4 @@ 這行字符串表示在更改組中描述的第一個文件中的文本行和第二個文件中的文本行。類
似於時間戳,簡短些。
空格  兩個文件都包含這一行。
-	 在第一個文件中刪除這一行。
+	 添加這一行到第一個文件中。

[me@linuxbox ~]$ diff -Naur file1.txt file2.txt > patchfile.txt
[me@linuxbox ~]$ patch < patchfile.txt
patching file file1.txt
[me@linuxbox ~]$ cat file1.txt
b
c
d
e

[me@linuxbox ~]$ echo "lowercase letters" | tr a-z A-Z
LOWERCASE LETTERS
[me@linuxbox ~]$ echo "lowercase letters" | tr [:lower:] A
AAAAAAAAA AAAAAAA

[me@linuxbox ~]$ tr -d '\r' < dos_file > unix_file
注:dos_file 是需要被轉換的文件,unix_file 是轉換後的結果。使用轉義序列 \r 來代表回車符

[me@linuxbox ~]$ echo "aaabbbccc" | tr -s ab
abccc
[me@linuxbox ~]$ echo "abcabcabc" | tr -s ab
abcabcabc

[me@linuxbox ~]$ echo "front" | sed 's/front/back/'
back
[me@linuxbox ~]$ echo "front" | sed 's_front_back_'
back
注:就是把front替換成back。

[me@linuxbox ~]$ echo "front" | sed '1s/front/back/'
back
[me@linuxbox ~]$ echo "front" | sed '2s/front/back/'
front

[me@linuxbox ~]$ sed -n '/SUSE/p' distros.txt
SUSE         10.2     12/07/2006
SUSE         11.0     06/19/2008
SUSE         10.3     10/04/2007
SUSE         10.1     05/11/2006
[me@linuxbox ~]$ sed -n '/SUSE/!p' distros.txt
Fedora         10       11/25/2008
Ubuntu         8.04     04/24/2008
Fedora         8        11/08/2007

[me@linuxbox ~]$ sed 's/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/' distros.txt
SUSE           10.2     2006-12-07
Fedora         10       2008-11-25
SUSE           11.0     2008-06-19
Ubuntu         8.04     2008-04-24
Fedora         8        2007-11-08
注:是由sed 's/regexp/replacement/' distros.txt基本模式得出
regexp = [0-9]{2}/[0-9]{2}/[0-9]{4}$ 
\3-\1-\2 就是三個子表達式,原順序改成3,1,2的順序
目的-- MM/DD/YYYY格式到 -> YYYY-MM-DD  即s/A/B/C$/3/2/1,\(和\)轉義字符。\3爲逆參數。

[me@linuxbox ~]$ echo "aaabbbccc" | sed 's/b/B/'
aaaBbbccc
[me@linuxbox ~]$ echo "aaabbbccc" | sed 's/b/B/g'
aaaBBBccc
注:我們看到雖然執行了替換操作,但是隻針對第一個字母 “b” 實例,然而剩餘的實例沒有更改。通過添加 g 標誌, 我們能夠更改所有的實例

[me@linuxbox ~]$ aspell check foo.txt
發佈了59 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章