Bo2SS

Bo2SS

9 數據提取、軟硬連接、線性篩、SED

課程內容#

數據提取操作#

| 命令 | 功能 | 命令 | 功能 |
|:----:|:----|:----:|:----|:----:|:----|:----:|:----|
|cut | 切分 | grep | 檢索 |
|sort | 排序 | wc | 統計字符、字數、行數 |
|uniq | 去重 | tee | 雙向重定向 |
|split | 文件切分 | xargs | 參數代換 |
|tr | 替換、壓縮、刪除 | | |

cut#

—— 菜刀

  • -d c 以字符 c 分割
    • 可用 "" 或 '' 包圍 c,很靈活
    • 默認為空格
  • -f [n/n-/n-m/-m] 選擇第 n 塊 / 第 n-end 塊 / 第 n-m 塊 / 第 1-m 塊
  • -b [n-/n-m/-m] 字節
  • -c [n-/n-m/-m] 字符

grep#

常見操作見:tldr grep

  • -c 統計搜尋到的次數 [文件為單位]
  • -n 順序輸出所在行號
  • -v 輸出不匹配的 [補集]
  • -C 3 輸出附近 3 行的內容
  • -i 大小寫敏感
  • [PS] -n、-c 衝突,優先顯示 - c 結果
  • 示例
    • 統計路徑下包含 doubleliu3 的行數
      • 圖片
      • 使用 cut+awk 或直接使用 awk
    • 查看 hz 相關正在運行的進程
      • 圖片
      • ps -ef:類似 Windows 下的任務管理器
      • 相比,ps -aux 顯示的信息更多,在早期偏向 UNIX 系統
      • [PS] ps -ef 中,PPID 是父進程的 ID

sort#

類似 Excel 的排序功能,默認根據行首按 ASCII 碼排序

  • -t 分隔符,默認為 TAB
  • -k 以哪個區間排序
  • -n 純數字排序
  • -r 反向排序
  • -u uniq [但不方便計數]
  • -f 忽略大小寫 [默認];-V [不忽略大小寫]

【示例】將用戶信息根據 uid 按純數字排序

cat /etc/passwd | sort -t : -k 3 -n

【經測試】

  • 排序時默認
  • 省略了特殊符號,如下劃線 "_"、"*"、"/" 等
  • 還忽略大小寫,排好序後把小寫放在大寫前面 [-V 可以不忽略大小寫]

wc#

  • -l 行數
  • -w 字數
  • -m 字符數;-c 字節數

【示例】

① 最近登錄系統的總次數

last | grep -v "^$" | grep -v "begins" | wc -l

② PATH 路徑的相關統計:字符數、單詞數、變量數、取最後一個變量
圖片

uniq#

連續的重複的才算重複,一般與 sort 配合

  • -i 忽略大小寫
  • -c 計數

【示例】統計最近用戶的登錄次數,根據次數從大到小排序

圖片

tee#

既顯示在終端,又寫進文件

  • 默認覆蓋原文件
  • -a 追加不覆蓋

【示例】

圖片

split#

切分一個文件,適合處理大文件

  • -l num 按 num 行切分
  • -b size 按 size 大小切分,512 [默認 byte]、512k、512m
    • 可能存在首行、末行不完整,所以可用下面方式👇
    • ❗ -C size 按最多 size 大小切分,並保證不破壞行數據!
  • -n num 按大小平分成 num 份

【示例】將 /etc 下的文件列表每 20 行切分出一個文件

圖片

xargs#

參數代換,適合不接收標準輸入的命令,等價於用命令替換符的方式

  • -exxx 讀到 "xxx" 結束

圖片

  • -p 執行整個指令前詢問
  • -n num 指定每次接收的參數個數⭐,而不是一次性全部傳入
    • 圖片
    • 適合只能讀一個參數的命令 [如 id] 或相關場景

tr#

對標準輸入的字符替換、壓縮、刪除,可查看 tldr tr

tr [選項] < 字符 / 字符集 1> < 字符 / 字符集 2>

  • 默認替換字符集 1👉字符集 2,一一對應
    • 字符集 1 較字符集 2 多出的字符,以字符集 2 最後一個字符作為替換
  • -c 替換所有不屬於字符集 1 的字符👉字符 2
  • -s 壓縮,將連續重複的字符 1👉一個字符 1 【❗與 - c 搭配時看字符 2】
  • -d 刪除所有屬於字符集 1 的字符
  • -t 先刪除字符集 1 中較字符集 2 多出的字符,再一一對應替換【❗ 注意與默認方式的區別】

【示例】

①簡單使用

圖片

  • -s 也需要參數,與 - c 搭配時默認用字符 2
  • -t 只管一一對應了的字符,字符集 1 比字符集 2 多出的字符不管

②詞頻統計

圖片

  • tr 替換👉排序👉去重計數👉排序👉顯示前幾名

軟、硬連接#

硬連接可以減少存儲使用,軟連接多了一個 inode 和 block

【背景介紹】

  • ext4 文件系統 —— 三個組成部分 ——inode、block、superblock
  • inode:文件結點
    • 一個 inode 對應一個文件
    • 存儲文件信息 [文件權限、所屬者、時間...] 和文件真實位置 [blocks 位置]
    • 如果存不下 blocks 位置,會用多級 blocks
  • block:文件真實存放位置,一個 block 一般是 4096 bytes
  • superblock:至少兩個,存儲文件系統的整體信息 [如 inode、block...]

【硬連接】相當於一個別名

【軟連接】相當於一個快捷方式

  • 創建了一個新的文件,擁有自己的 inode,指向一個 block [存儲文件的真實位置]
  • 文件類型為 link
  • [PS] 比硬連接更常用

線性篩#

  • 圖片
  • shell 中的數組沒必要初始化,一開始就為空

    • 其實不管什麼變量,一開始都是空,沒有類型
  • 學會【變量 x == x】的判空操作

  • 數組的下標可以直接使用變量名,可以不用 ${} 包裹

【與素數篩的效果比較】

求 2~20000 的素數和

  • 圖片
  • 在 shell 中,效果還沒有素數篩好,可能原因是:

    • shell 涉及很多系統的調用,不能純看數學層面了
    • 執行 shell 腳本會把 CPU 跑滿,與 C 語言中的效果不具有可比性
    • 取餘操作

➕SED 腳本編輯#

主要用於編輯腳本,語法可借鑒 vim

【常用操作】替換 [批量、按行、匹配]、刪除

# 替換每行匹配的第一個字符串模式 [支持正則表達式]
sed 's/{{regex}}/{{replace}}/' {{filename}}
# 替換匹配的行的第一個字符串、刪除匹配的行
sed '/{{line_pattern}}/s/{{regex}}/{{replace}}/' {{filename}}
sed '/{{line_pattern}}/d' {{filename}}
# 可以使用其它分割符,比如'#',應對需要用到'/'字符的場景
sed 's#{{regex}}#{{replace}}#' {{filename}}
# 刪除兩個匹配模式之間的所有行
sed '/{{regex}}/,/{{regex}}/d' {{filename}}
# [特殊]刪除匹配行之後/之前的內容
sed '/{{regex}}/,$d' {{filename}}
sed '/{{regex}}/,$!d' {{filename}}

【命令演示】

① 上述常用命令按順序操作

圖片

② 用於替換配置文件的某些配置

  • 圖片
  • 刪除 👉 添加

  • 刪除前做備份

  • 添加時加入標識符 #newadd,方便之後用 sed 操作

  • 直接刪除再添加,而不是直接替換,可避免繁瑣的模式匹配 [參數值]

隨堂練習#

  1. 求字符串中所有數字之和:"1 2 3 4 5 6 7 9 a v 你好 . /8"
  2. 將文件中所有大寫字母轉換為小寫:echo "ABCefg" >> test.log
  3. 找到PATH變量中的最後一個路徑
  4. 使用last命令,輸出所有的重啟信息
  5. /etc/passwd中的內容按照用戶名排序
  6. /etc/passwd中的內容按uid排序
  7. 在雲主機上查找近 2 個月系統登錄用戶的總人次
  8. 將雲主機中近 2 個月登錄的所有用戶名,按照次數排序,並輸出次數
  9. 將本地的/etc目錄下的文件及目錄名,每十條保存到一個文件中
  10. /etc/passwd中存放的第 10 到 20 個用戶,輸出uidgidgroups
  11. 按照用戶名查看/etc/passwd中的用戶,讀到'sync'用戶時結束,並輸出用戶的uidgidgroups
  12. 詞頻統計

① 使用下面的命令生成一個文本文件 test.txt

cat >> test.txt << xxx
nihao hello hello 你好 
nihao
hello 
ls
cd
world
pwd
xxx

② 統計 a.txt 中各詞的詞頻,並按照從大到小的順序輸出。
答案

【1】
  [巧妙解法,需在bash下]
    echo "1 2 3 4 5 6 7 9 a v 你好 . /8" | tr -s -c 0-9 "\n" | echo $[`tr "\n" "+"`0]
  [for循環]
    sum=0
    for i in `echo "1 2 3 4 5 6 7 9 a v 你好 . /8" | tr -s -c 0-9 "\n"`; do
    for> sum=$[$sum+$i]
    for> done
  [awk解法1]
    echo "1 2 3 4 5 6 7 9 a v 你好 . /8" | tr -s -c 0-9 "\n" | awk -v sum=0 '{sum += $1} END { print sum }'
  [awk解法2]
    echo "1 2 3 4 5 6 7 9 a v 你好 . /8" | tr -s -c 0-9 " " | awk -v sum=0 '{for (i = 1; i <= NF; i++) {sum += $i} } END{print sum}'
【2】 cat test.log | tr A-Z a-z > test.log
【3】 echo ${PATH} | tr ":" "\n" | tail -1
【4】 last | grep "reboot"
【5】 cat /etc/passwd | sort
【6】 cat /etc/passwd | sort -t : -k 3 -n
【7】 last -f /var/log/wtmp.1 -f /var/log/wtmp | grep -v "^$" | grep -v "begins" | grep -v "reboot" | grep -v "shutdown" | wc -l
【8】 last -f /var/log/wtmp.1 -f /var/log/wtmp | grep -v "^$" | grep -v "begins" | grep -v "reboot" | grep -v "shutdown" | cut -d " " -f 1 | sort | uniq -c | sort -n -r
【9】 ls /etc | split -l 10
【10】 cat /etc/passwd | head -20 | tail -10 | cut -d : -f 1 | xargs -n 1 id
【11】 cat /etc/passwd | cut -d : -f 1 | xargs -e"sync" -n 1 id
【12】
  cat test.txt | tr -s " " "\n" | sort | uniq -c | sort -n -r
  [如果想讓詞在前、次數在後,使用awk顛倒]
    cat test.txt | tr -s " " "\n" | sort | uniq -c | sort -n -r | awk '{print $2, $1}'

Tips#

  • 面試常考:詞頻統計
    • 圖片
    • tr 替換👉排序👉去重計數👉排序👉顯示前幾名

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。