shell中文本處理的基本方式

2021-06-14

關鍵字:


1、echo

echo是shell中最常用的文本輸出命令。其基本語法如下所示:

echo [option] string...

echo命令可用的 option 如下表所示:

option 釋義
-E 默認選項,當echo不攜帶任何選項時即相當於帶上了此選項。此選項表示不解析string中的轉義字符。
-e 與 -E 相對,使用此選項後即表示會解析string中的轉義字符。
-n 在輸出完string後不追加一個換行字符。

 

另外,echo命令支持的轉義字符如下表示所:

轉義字符 含義
\a 報警符。相當於ASCII中的BEL字符。
\b 退格符。輸出此轉義字符會將已輸出的一個字符“喫掉”。
\c 禁止繼續輸出文本。輸出此轉義字符後,同一條echo命令後面要輸出的文本均不會再執行。
\f 換頁符
\n 換行符
\r 回車符
\t 水平製表符
\v 垂直製表符
\\ 輸出一個反斜線

 

echo 命令默認將文本輸出到控制檯,即作爲打印信息顯示在屏幕上。可以使用重定向符將文本流往文件系統輸出。具體如下所示:

#!/bin/bash

#將文本保存到 /var/file1 文件中去
echo "hello world" > /var/file1

#將文本追加到 /var/file1 文件中去
echo "hello rust" >> /var/file1

 

下面結合echo命令的選項及轉義字符編寫一個 0% ~ 100% 的進度條顯示shell函數。該函數不同於傳統的echo輸出命令會爲每一個新值開闢一個新行,而是在數值更新時直接將舊值更新爲新值。就類似於日常手機或網頁中的百分比進度條那種效果。這個shell函數的核心思想就是使用 \b 退格轉義字符,在百分比值更新時將已輸出在屏幕上的舊值“喫掉”,然後再填充以新值從而達到我們想要的效果。

 

以下是完整的源碼:

#!/bin/bash

#定義打印百分比值的函數
function progress ()
{
    #參數檢查,調用此函數時必須傳遞一個參數
    if [ $# -ne 1 ]; then
        echo "Usage:"
        echo "  progress [percentage]"
        echo "eg:"
        echo "  progress 0"
        echo "  progress 100"
        return 1
    fi
    
    #參數類型檢查,傳遞進來的參數必須是 0 ~ 100 之間的整數
    local progress_ttmp_1=1
    if [ $1 -ge 0 2> /dev/null -a $1 -le 100 2> /dev/null ]; then
        progress_ttmp_1=0
    fi
    
    if [ $progress_ttmp_1 -ne 0 ]; then
        echo "Can only accept integer parameter"
        return 2
    fi

    #百分比值更新。progress_ttmp_2 變量純粹是爲了標識是否第一次調用此函數。這關係到如何輸出\b字符
    if [ "$progress_ttmp_2" = "1" ]; then
        #控制好\b字符的輸出數量從而保證輸出格式不出錯。
        if [ $1 -le 10 ]; then
            echo -ne "\b\b$1%"
        else
            echo -ne "\b\b\b$1%"
        fi
    else
        progress_ttmp_2="1"
        #首次調用函數,無須輸出\b轉義字符
        echo -n "$1%"
    fi
}


#模擬一個從 0 ~ 100 的進度狀態流程
for (( i=0; i<101; i++ ))
do
    progress $i
    #當函數成功執行時延時10毫秒來模擬後臺作業耗時
    if [ $? -eq 0 ]; then
        sleep 0.01
    else
        #進度打印出錯時直接退出
        break
    fi
done

 

 

2、fold

fold命令的功能是將超過指定寬度的文本行強制做換行處理。其語法如下所示:

fold [option] [file]...

fold 命令可以同時處理多個文件,不同文件之間以空格字符隔開。

 

option的可選值如下表所示:

選項 含義
-b 按字節計算寬度。超過-w選項指定的字節數時爲此行做換行處理。默認情況下按列數計算(按字符)。
-s 在空格處做換行操作以避免單詞被折斷。
-w 指定行寬度上限。超過此選項指定的寬度值時自動爲此行做換行處理。默認的寬度是80列後換行。

具體的使用示例如下所示:

fold -w 55 story.txt
fold -s -w 86 story.txt
fold -b story.txt
fold -b -w 100 story.txt

 

 

3、fmt

與fold命令類似,fmt命令的功能也是將超過指定寬度的文本行強制換行。但是fmt的功能會多於fold命令。其語法如下所示:

fmt [-width] [option] [file]

-width參數用於指定文本行的列數,默認爲75列,即75個字符後換行。

 

此命令同樣可以同時處理多個文件,不同文件之間以空格隔開。

 

option的可選值如下表所示:

選項 含義
-c 保留每個段落的前兩行的縮進。
-t 與-c選項功能類似,但是在使用此選項時,每個段落的第1行和第2行的縮進必須是不相同的,否則第1行被看做一個單獨的段落。
-s 只折斷超出指定寬度的行,不合並少於指定寬度的行。默認情況下是會合並少於指定寬度的行的。
-u 統一空格數量,單詞之間保留1個空格,句子之間保留2個空格。
-w 指定每個行的最大寬度,默認爲75列。

 

以下是具體的示例程序:

fmt -c -w 80 story.txt
fmt -s -c -w 80 story.txt
fmt -20 -s story.txt

 

 

4、rev

rev命令的作用是反轉字符順序。即將文本中每一行的字符倒轉過來。語法如下所示:

rev [file]...

多個文件之間以空格字符隔開。

 

使用示例如下所示:

rev story.txt

 

 

5、文本統計

1、輸出帶有行號的文本

可以使用 cat 命令帶參數,如下所示:

cat -n story.txt

將輸出的流重定向至文件中即可完成格式化修改。

 

除此之外,nl 命令也可爲文件流帶上行號。其語法如下所示:

nl [option] [file]

nl命令支持的option較多,常用的幾個則如下表所示:

option 含義
-b 顯示風格控制。可取 a , t , n 作爲值。a表示爲所有行添加行號。t表示僅爲非空行添加行號(默認)。n表示不添加行號。
-i 行號的增量,默認爲1。
-v 行號的起始值,默認爲1。

使用示例如下所示:

nl story.txt
nl -b a story.txt

 

 

2、統計行數

使用 grep 命令加 -c 選項可以統計符合條件的結果行數。其示例代碼如下:

grep -c "keyword" story.txt

 

另外,還有一個更專業的統計文本專用的命令:wc。

 

wc命令即 word count 的縮寫。其語法如下所示:

wc [option] [file]

option可用的值如下表所示:

option 含義
-c 統計文本的字節數。
-m 統計字符數。
-l 統計行數。
-L 統計最長的文本行的長度。
-w 統計單詞數。

具體示例如下所示:

wc -m story.txt
wc -l story.txt

直接使用wc命令統計文件中文本的數據時會在統計結果末尾顯示出被統計文件名。如果不想顯示此文件名,可以配合cat和管線命令來去除,具體用法如下所示:

cat story.txt | wc -m
cat story.txt | wc -l

 

  

6、cut

cut命令的作用是將文本中的數據按指定分隔符提取若干文本列。其語法如下所示:

cat [option] [file]

常用的option值如下表所示:

option 含義
-b 只選擇指定的字節。
-c 只選擇指定的字符。
-d 自定義列分隔符,默認爲製表符。
-f 只選擇列表中指定的文本列。文本列號從1開始,多個列之間以逗號隔開,連續列以減號代替。
-n 取消分隔多字節字符
-s 不輸出不包含列分隔符的行。

具體示例如下所示:

cut -d ":" -f 1,7 /etc/passwd

表示將 /etc/passwd 文件以 ":" 作爲分隔符,提取其第1列與第7列的數據。

cut -d ":" -f 1-4 /etc/passwd

功能同上,這次提取的是第1 ~ 第4列的數據。

cut -d ":" -f 3- /etc/passwd

功能同上,這次提取的是第3列及以後的數據。

cut -d ":" -f 1,2,4-7 /etc/passwd

功能類似於上面幾條。

 

可以不指定分隔符只提取文本中指定列號處的字符數據:

cut -c 1,3,5 /etc/passwd

 

 

7、paste

paste命令與cut命令是相對的一組命令,它負責將多個文件中的內容合併起來。其語法如下所示:

paste [option] [file]

option常用的值如下表所示:

option 含義
-d 指定拼接結果中列分隔符。默認使用製表符分隔。
-s 將多個文件串行拼接,即後面的文件內容以追加的方式添加到前一個文件內容中。

具體示例如下所示:

paste story.txt author.txt > book_info.txt

paste命令本身不支持選列拼接,但是可以通過與cut命令配合來達到此效果,示例如下:

cut -f 1,2 phones.txt > phones.tmp
cut -f 2 authors.txt > authores.tmp
paste authores.tmp phones.tmp > contacts.txt

 

 

8、tr

tr 命令是 translate 的縮寫。其功能是批量替換文本中的字符。語法如下:

tr [option] [set1] [set2]

option常用的值如下表所示:

option 含義
-c 用字符集set2替換字符集set1中沒有包含的字符。
-d 刪除字符集set1中的所有字符,不執行替換操作。此時無須傳入set2參數。
-s 壓縮set1中重複的字符。
-t 將字符集set1用set2轉換。

 

如想去掉文本中所有的空行:

cat story.txt | tr -s ["\n"]

 

刪除指定字符:

tr -d [rust] < story.txt

此舉,會將 story.txt 中所有的字母 r , u , s, t 刪除掉。

 

個人認爲,tr命令特別不實用。

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章