【shell 練習】菜雞的自我修養~

前言

工作中經常有需要寫一個簡單shell腳本的情景,每次都要花費一些時間來用啥學啥,加起來用掉很多時間,所以打算用shell刷一些題,來鍛鍊自己的shell能力~


1. 詞頻統計

題目描述

寫一個 bash 腳本以統計一個文本文件 words.txt 中每個單詞出現的頻率。
爲了簡單起見,你可以假設:
words.txt只包括小寫字母和 ’ ’ 。
每個單詞只由小寫字母組成。
單詞間由一個或多個空格字符分隔。

做法

1. map

當成一個題目來看的話,最先想到就直接map就結束了,搜索後學習了一波map的用法,但是這裏map不會按照value把key排序,所以加了個桶排,實現起來很蠢,對,我很蠢~

#!/bin/bash
declare -A map
declare -A rmap
words=$(cat ./words.txt)
for i in $words
do
    map[$i]=$((${map[$i]}+1))
done
for i in ${!map[@]}
do
    rmap[${map[$i]}]=$i
done
for i in $(seq 10000 -1 1)
do
    if [ "${rmap[$i]}" != "" ];
    then
        echo ${rmap[$i]} $i
    fi
done

2. tr + sort + uniq + awk

首先用tr命令去掉文本中多餘的空格和換行符,之後對整個文本sort,用uniq -c 來去重並展示出現次數。
之後再按照數值sort一次用awk換列輸出即可。

cat words.txt | tr -s ' ' '\n' | sort  | uniq -c | sort -r | awk '{print $2 " " $1}'

知識點

0.基本操作

1. for 循環 1 - 10 
for i in $(seq 1 10) 
do
	echo $i
done
2. for 循環 10 - 1
其實增序for循環時隱藏了一個變量 1 ,所以降序時加上-1即可。
for i in $(seq 10 -1 1)
3. if 語句
if [ command ]; then
	#符合該條件執行的語句
elif [ command ]; then
	#符合該條件執行的語句
else 
	#符合該條件執行的語句
fi 
4. 字符串判等
[ "$a" == "$b" ]
5. 字符串判空
[ "$a" == "" ]

1.declare

declare 用來給變量 聲明/取消聲明 某個屬性。

declare [+/-][選項] 變量名
選項:
   -:給變量捨得類型屬性
   +:取消變量的類型屬性
  -a:將變量聲明爲數組型
  -a:  將變量聲明爲map型
  -i:將變量聲明爲整型
  -x:將變量聲明爲環境變量
  -r:將變量聲明爲只讀變量
  -p:查看變量的被聲明的類型

2. map

1. 聲明變量a爲 map
declare -A a
2. 遍歷整個map
for i in ${!map[@]}
do
   echo $i
done
3. 使用map的value值
${map[$key]}

3.tr

tr的用途

Linux tr 命令用於轉換或刪除文件中的字符。
tr 指令從標準輸入設備讀取數據,經過字符串轉譯後,將結果輸出到標準輸出設備。

tr的語法

tr [OPTION]…SET1[SET2]

-c, --complement:反選設定字符。也就是符合 SET1 的部份不做處理,不符合的剩餘部份才進行轉換
-d, --delete:刪除指令字符
-s, --squeeze-repeats:縮減連續重複的字符成指定的單個字符
-t, --truncate-set1:削減 SET1 指定範圍,使之與 SET2 設定長度相等
–help:顯示程序用法信息
–version:顯示程序本身的版本信息

用法示例

1. 將a.txt中所有的a替換成b
cat a.txt | tr 'a' 'b'
2. 將a.txt中所有的a替換成b,c替換成d
cat a.txt | tr 'ab' 'cd'
3. 將a.txt中所有小寫字母替換成對應的大寫字母
cat a.txt | tr a-z A-Z
4. 合併 a.txt中所有連續的空格及換行
cat a.txt | tr -s ' ' '\n'
5. -t的使用,使SET1長度和SET2相等,例如下面的效果是把a.txt中所有a替換成b.
因爲SET1的長度被限制爲與SET2相等。
cat a.txt | tr -t 'ac' 'b'

4.sort

sort 語法

用法:sort [選項]… [文件]…
串聯排序所有指定文件並將結果寫到標準輸出。

排序選項:

-b, --ignore-leading-blanks 忽略前導的空白區域
-d, --dictionary-order 只考慮空白區域和字母字符
-f, --ignore-case 忽略字母大小寫
-g, --general-numeric-sort 按照常規數值排序
-i, --ignore-nonprinting 只排序可打印字符
-n, --numeric-sort 根據字符串數值比較(整個字符串的字典序)
-r, --reverse 逆序輸出排序結果

其他選項:

-c, --check, --check=diagnose-first 檢查輸入是否已排序,若已有序則不進行操作
-k, --key=位置1[,位置2] 在位置1 開始一個key,在位置2 終止(默認爲行尾)
-m, --merge 合併已排序的文件,不再進行排序
-o, --output=文件 將結果寫入到文件而非標準輸出
-t, --field-separator=分隔符 使用指定的分隔符代替非空格到空格的轉換
-u, --unique 配合-c,嚴格校驗排序;不配合-c,則只輸出一次排序結果

sort的單位是每一行。

用法示例

將a.txt中的每一行按照字典序排序
cat a.txt | sort
將a.txt中的每一行,按照常規數字排序,支持科學計數法
cat a.txt | sort -g
將a.txt中的每一行排序並去重
cat a.txt | sort -u

uniq

uniq 命令用於檢查及刪除文本文件中重複出現的行列,一般與 sort 命令結合使用。

uniq 語法

-c: 在每列旁邊顯示該行重複出現的次數。

-d: 僅顯示重複出現的行列,顯示一行。

-D: 顯示所有重複出現的行列,有幾行顯示幾行。

-u: 僅顯示出一次的行列

-i: 忽略大小寫字符的不同

-f Fields: 忽略比較指定的列數。

-s N: 忽略比較前面的N個字符。
-w N: 對每行第N個字符以後的內容不作比較。

用法示例

對a.txt文本直接去重
cat a.txt | uniq 
對a.txt文本去重後旁邊顯示出現次數 
cat a.txt | uniq -c 

awk

awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤爲強大。簡單來說awk就是把文件逐行的讀入,以空格爲默認分隔符將每行切片,切開的部分再進行各種分析處理。

awk內置變量

ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行 -F選項
NF 瀏覽記錄的域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,…以此類推。
$NF是number finally,表示最後一列的信息,跟變量NF是有區別的,變量NF統計的是每行列的總數

awk常用語法

用途 輸入文本 a.txt 命令 輸出文本
篩選包含關鍵字的行 a b c
c d f
b a g
awk ‘/b/’ a.txt a b c
b a g
篩選包含關鍵字的行
並輸出某一列
a b c
c d f
b a g
awk ‘/b/ {print $2}’ a.txt b
a
使用printf輸出,更清晰 a b c
c d f
b a g
awk ‘/b/ {printf ("%s\n",$2)}’ a.txt b
a
只保留第二行信息 a b c
c d f
b a g
awk ‘NR==2 {printf ("%s",$2)}’ a.txt c d f
設置特定的分隔符並輸出第一列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$2)}’ a.txt b
d
a
設置特定的分隔符並輸出最後一列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$NF)}’ a.txt c
f
g
設置特定的分隔符並輸出倒數第二列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$NF-1)}’ a.txt b
d
a
獲取第二到第三行的第一列信息 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{if(NR>=2&&NR<=3) print $1}’ a.txt c
b
多個分隔符 1:2?3,4 awk -F ‘[,:?]’ ‘{print $4}’ words.txt 4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章