grep
、tr
、sed
、awk
是幾個很常見的標準串流 Standard Streams 處理工具,靠著regex的加持,這些工具使用在 I/O redirection 比起寫個python script快多了,唯一的壞處就是options太多,容易遺忘。本文主要紀錄上述工具使用筆記與心得。
(撰於 2016 年年初,致青春)
sed
是 Stream EDitor 的縮寫,最常用來處理pipeline。特色是一次只讀取一行input到buffer處理,導向至「標準輸出(STDOUT)」後,再處理下一行。
取代/刪除/插入 搜尋到之匹配字串
#
sed [options] script [inputfile]
-n
: 不輸出至 標準輸出 (預設是 each lines,通常配合p
flag使用)-i
: edit file in-place,直接修改檔案-E
: 使用延伸正則表示式 (ERE,即不需跳脫?+|{(
,但仍有例外)-f
: 執行 script file-e script
: 執行-e
後的字串 (evaluate)
如果沒有指定
-e
,第一個non-options的參數將會當成 script執行
script就是sed將執行的範圍和command的集合,表示法如下:
[addr1][,addr2]command[/pattern][/replacement]/[flags]
其中 addr (address) 代表作用行數 (位址) 範圍,例如 1-3 為 1,3
, 5至資料末為5,$
。
事實上,address也可以用pattern matching來表示匹配的行數。例如
/^http:/,/^sftp:/
表示作用位址從**第一次匹配
^http:
的行數到最後一次匹配^sftp
的行數範圍內。
sed 的 commands 則有許多種,常見如下:
d
: 刪除指定位址,例如sed '3,5d'
刪除 3-5 行p
: 印出指定行,通常和-n
option配合,sed '0,6p'
印出 0-6 行a
: 在指定行之下新增一行(各家實作有差異,略)i
: 在指定行之上插入一行(各家實作有差異,略)s
: 取代指定pattern,和vim
取代類似。例如將2-8行內的**[Dd]og取代為cat**:
sed '2,8s/[Dd]og/cat/g'
command
s
(substitute) 常見的flag有:
p
: 印出g
: 取代行內所有match occurrences,沒寫則只取代第一個i
: 忽略大小寫數字
: 取代幾個occurrances
為了增加可讀性,s
command可替換分隔符號 (delimeter),接在s
後的第一個字元即會成為分隔符。 例如下列會將所有匹配usr
位址行數中的slash/
取代為垂直線|
,其中就將預設分隔符 /
替換成 :
:
cat /etc/passwd | sed '/usr/ /bin/ s:/:|:g'
就是輸入資料,若讀取standard input,則可省略。
- Mac built-in sed manual
- GNU sed manual.
- 阿旺的 Linux 開竅手冊
awk
和其他 command line tool 差異較大,提供許多與 C 語言相近的語法,屬於小而巧的的直譯語言。預設情況下,awk
以空白 (white space) 作分隔符號 (delimeter),方便使用者取得特定欄位。
身為一種程式語言,awk
當然也可執行複雜的text processing,但直至今日 (2016.8),已有更強大的語言可以替代awk
來處理文字 (e.g. perl & python)。不過,善用 awk
的 one-line command 結合 pipeline redirect,依然是快速有效的處理方式。在此也僅紀錄簡單常見的用法
處理格式化的表格、文字報表格式化輸出
awk 'pattern { action }' [input-file ...]
理解 awk
之前,先看接下來的例子:
ls -l | awk 'FNR > 1 && FNR < 4 { print $3,$9 }'
# weihanglo Desktop
# weihanglo Documents
在bash的世界裡,雙引號內的字串會被interpolate,單引號中的內容中才會保留字面量。awk
為了防止預設欄位變數被取代,慣例上常將欲執行的程式寫在單引號' ... '
。
awk
program 中的 pattern 作用如同 grep
,篩選符合 pattern 的資料行,再繼續執行 { ... }
中的敘述。FNR
是awk
內建的變數,>
<
是awk
的運算子 (operator),與 C 語言無異,以下列出常用的運算子及內建變數:
Operator | Description |
---|---|
== |
相等 |
!= |
不相等 |
> |
大於 |
>= |
大於等於 |
< |
小於 |
<= |
小於等於 |
&& |
且 (and) |
` | |
~ |
符合regex |
!~ |
不符合regex |
而程式區塊 { ... }
則支援多種敘述 (statement),例如:for (var in array) ..
、print ...
等。