Linux 文本處理(3) (cut、grep、awk、sort、uniq、wc)
前言
在前面兩篇關於文本處理的文章
Linux 文本處理(1) (查看文件內容)以及
Linux 文本處理(2) (寫入資料到文件)介紹了基本的文本操作,今日就來介紹其他較為進階的文本操作指令,包含搜尋關鍵字、排序、切割文本等操作。
cut (切割、擷取文字)
常用來切割文字,擷取特定位置的字符,或是以特定的分割符,擷取特定的欄位,很像一般程式語言中的 split()
方法,會以每行
作為單位執行
常用參數
-c
:擷取特定位置的字符(從1開始),擷取多個位置用,
分開,連續位置用-
-f
:用分割符分割後,擷取哪列的值,多列也是用,
分隔,都配合-d
使用,沒有設定分隔符就是單純把每行印出來-d
:指定分割符
以下為使用範例
擷取特定位置字符
切割文本文件每行的第1至3个字符:
1
2
3
4
5
6
7
8
9cut -c 1-3 文件名.txt
# 假設文本內容為
abcddd
bbcddd
# 輸出會為
abc
bbc擷取文件內每行的1,3,5 的字符
1
2
3
4
5
6
7
8
9cut -c 1,3,5 文件名.txt
# 假設文本內容為
abcddd
bbcddd
# 輸出會為
acd
bcd擷取文件內每行1至3、6至9 的字符
1
2
3
4
5
6
7
8
9cut -c 1-3,6-9 文件名.txt
# 假設文本內容為
abcdddasdg
bbcdddasdg
# 輸出會為
abcdas
bbcdas
以分隔符分割,擷取欄位值
切割以逗號分隔的CSV文件的第2列和第4列:
1
cut -d ',' -f 2,4 數據.csv
切割以冒号分隔的密碼文件的用户名字段:
1
cut -d ':' -f 1 /etc/passwd
與其他命令結合使用
從標準輸入讀取數據,切割第1、第3和第5个字符:
1
echo "Hello,World" | cut -c 1,3,5
grep (搜尋關鍵字)
grep
、 sed
、awk
並稱linux 文本處理三劍客
grep
是用來搜尋關鍵字
,它可以使用正規表示式搜尋文字,並把匹配的行打印出來。全稱是 Global Regular Expression Print。
常用參數
-i
:忽略大小寫進行搜索-r
或-R
:遞歸地在目錄
中搜索匹配的文本-l
:顯示包含匹配文本的文件名
。通常配合通配符*
使用-n
:顯示匹配文本所在的行號-v
:反轉搜索,只顯示不匹配模式的行-c
:顯示匹配行的數量-A num
:顯示匹配行及後面
num 行的內容-B num
:顯示匹配行及前面
num 行的內容-C num
:顯示匹配行以及前後
各 num 行的內容--color=always
:關鍵字高亮
常用範例
搜尋關鍵字
在文件 “file.txt” 中搜索包含 “apple” 的行:
1
grep "apple" file.txt
針對目錄遞歸搜尋(-r)
在目錄 “/home” 及其子目錄中搜索包含 “error” 的文本文件:
1
grep -r "error" /home
忽略大小寫(-i)
忽略大小寫,在文件 “file.txt” 中搜索 “Code: 502”:
1
grep -i "Code: 502" file.txt
顯示行號(-n)
在文件 “file.txt” 中搜索 “apple” 並顯示行號:
1
grep -n "apple" file.txt
顯示包含匹配文本的文件名(-l)
在當前目錄搜尋顯示包含 “apple” 的文件名,而不顯示匹配的行:
1
grep -l "apple" *
在指定目錄還有其子目錄,搜尋內容包含”test”的文件名:
1
grep -r "test" -l /home/
搜尋指定目錄下的文件,內容包含”test”的文件名:
1
grep "test" -l /home/*
顯示匹配行及前後num行(-C數字)
搜尋關鍵字,顯示匹配行及其後4行
1
2
grep -C4 "status: 502" 2020-1-1.log
關鍵字高亮 --color=always
- 關鍵字高亮,如果有用到管道,需要兩個都加
1
grep -C4 "status: 502" 2020-1-1.log --color=always | grep -C4 "url" --color=always
egrep (grep高配版)
grep 的高級版,可以同時搜尋多個關鍵字
1
egrep "A|B" 文件名.txt
awk (以分隔符擷取文字)
簡單來說就是逐行讀取文本,以 空格 or Tab
將每行分割成小單位,也可以自訂分隔符號,最後將結果輸出
語法格式
1 |
|
其中
{動作}
最常使用的是 print,還有其他如printf (格式化輸出)、if 語句,操作一些內置的函數如 length() 獲取字串的長度、substr() 擷取字串等如果指定
條件
,當條件符合時才會執行動作
常用參數
-F
:指定分隔符,默認為空格 or Tab
-f
:使用awk腳本,來處理文本-v
:awk需要使用shell 裡面的變數時,需要先用-v 定義,無法直接使用
常用的變數
$0
: 打印整行 ,之後的數字代表字符以分隔符分隔後所在的位置 $1、$2…以此類推NR
: 每行的行號NF
: 每行用空格分隔後,字段的數量
內置變數
前面都不需要加$
FILENAME
: 當前文件名FS
: 分隔符,默認為 空格 or TabRS
: 行分隔符,默認為 換行符OFS
: 輸出的字段的分隔符,默認為空格,可以用 OFS=”~” 來指定,前面加上-v
ORS
: 輸出行的分隔符,默認為空格OFMT
: 輸出的數字的格式,默認為%.6gNF
: 每行用空格分隔後,字段的數量, 所以也可以用此找出每行的最後一個字
內置函數
toupper()
:大寫tolower()
:小寫length()
: 長度substr()
: 擷取字串sin()
: 正弦cos()
: 余弦sqrt()
: 平方根rand()
: 隨機數
常用範例
基本用法
有一文本test.txt
,內容為this is a test
打印出整行
1
awk '{print $0}'
Output:
1
this is a test
打印出每行 以空格分隔後的第一個單詞
1
awk '{print $1}'
Output:
1
this
將分隔符設定為 : 並打印第二個字
1
awk -F ':' '{print $2}'
Output:
1
is a
使用某個awk腳本處理文件
1
awk -f {awk脚本} {文件名}
使用shell 裏面的變數
1
2count=100
awk -v cc=$count {print cc}Output:
1
100
設定輸入自段的分隔符(OFS),加上
-v
1
2
awk -v OFS='\n' -F '-' '{print $2}'
設定條件
有一文本 awk_test_file
,內容如下
1 |
|
打印出 不包含 is 的行
1
awk '$0 !~ /is/' awk_test_file
Output:
1
23 Are you like awk
10 There are orange,apple,mongo打印出奇數行
1
awk 'NR % 2 == 1 {print $0}' awk_test_file
Output:
1
22 this is a test
This's a test除了打印變數,如果想要打印一些字符用””包起來
1
awk '{print NR ") " $0}' awk_test_file
Output:
1
2
3
41) 2 this is a test
2) 3 Are you like awk
3) This's a test
4) 10 There are orange,apple,mongo
if 語句
比較複雜的情況才需要用,不然用一般的條件判斷就行了
if 需要寫在 {動作}
裡面
else 前記得要分號;
- 打印奇數行,其他就打印x
1
awk '{if(NR % 2 == 1) print $0; else print "x"}' awk_test_file
Output:
1
2
3
42 this is a test
x
This's a test
x
內置函數用法
- substr(字符串, 起始位置, 长度)
1
echo "Hello, World" | awk '{ print substr($0, 1, 5) }'
Output:
1
Hello
sort (排序)
用於對文本文件中的內容進行 **排序
**,按照字母順序or數字順序,以每行
作為單位執行
若未指定文件名,sort
命令將會從標準輸入中讀取資料。
常用參數
-r
:倒序排序-f
:忽略大小排序-k
:根據指定的欄位進行排序(每個欄位預設以\t(空格)
分割)。例如,k 2
表示按照第二個欄位進行排序。-n
:按照數字大小進行排序,而不是用英文-t
:指定欄位分隔符-u
:重複的行只保留一行
以下是常用範例
排序
對文本文件進行字母順序排序:
1
sort 文件名.txt
以數字進行排序(-n)
對包含數字的檔案進行數值排序:
1
sort -n 文件名.txt # 如果沒有數字就預設使用英文字母排序
指定分隔符,選擇特定欄位進行排序(-t)
對包含 CSV 資料的檔案,依照第二個欄位的數值進行排序:
1
sort -t ',' -k 2 資料.csv
倒序(-r)
對文本文件進行倒序排序並移除重複的行:
1
sort -r 文件名.txt
去重複(-u)
對文本文件進型排序並移除重複的行:
1
sort -u 文件名.txt
uniq (去重複)
主要用於處理已經排序過的文本文件,能夠去除重複
的行或報告重複行的數量。
常用參數
-c
:除了顯示去重複後的數據外,也會在每行顯示該行文字出現的數量-d
:只顯示重複行 (exclude 不重複行)-i
:去重複時,忽略大小寫
常用範例
去重複
去除已排序文件中連續重複的行:
1
uniq 文件名.txt
顯示重複數量(-c)
顯示已排序文件中每行重複的數量:
1
uniq -c 文件名.txt
僅顯示重複行(-d)
僅顯示已排序文件中重複的行,去除不重複的行:
1
uniq -d 文件名.txt
忽略大小寫(-i)
忽略大小寫,去除已排序文件中連續重複的行:
1
uniq -i 文件名.txt
搭配sort指令使用
搭配sort 指令使用
1
sort 文件名.txt | uniq -c
搭配sort、awk 指令使用,打印出兩個文件不一樣的部分
1
2
3
4
5
6
7
8
9
10
11#!/bin/bash
old=`tr ',' '\n' < o_content | awk -v OFS='\n' -F '-' '{print $2}'`
new=`tr ',' '\n' < n_content | awk -v OFS='\n' -F '-' '{print $2}'`
# 執行去重複, 只打印出 不重複的部分
# "" 包注可以保留制表符 \n \t 那些
echo "$old$new" | sort | uniq -c | awk '$1 == 1 {print $0}'
wc (計數)
用來計算文本文件內各項數值的數量
沒有輸入任何參數,預設輸出該文件有 幾行、幾個單字、幾個byte
常用參數
-l
:有幾行
,通常日誌每個欄位都用行區分,所以這個是最泛用的-w
:有幾個單字
,hello world 算2個單字-c
:有幾個byte
-m
:有幾個char
常用範例
顯示幾行(-l)
該文件有幾行
1
wc -l 文件名.txt
搭配其他指令,計算筆數
搭配其他指令找到的資料,計算有幾筆
1
grep "status: 502" 文件名.txt | wc -l
tr (取代文字)
可以取代一個文本內的文字
語法格式
1 |
|
常用範例
- 將文本內的
,
替換成\n
1 |
|