# 【教學筆記 02】Linux 指令介紹
內容:Linux 指令介紹
---
[目錄](https://hackmd.io/Y7i9O4hCQu6xOJ94__PhNg)
[教學筆記 01:編碼、檔案、斷行字元、Excel、其他基礎知識介紹](https://hackmd.io/7-FajauqT62vXpxOViWzBw)
教學筆記 02:Linux 指令介紹
[教學筆記 03:awk 指令介紹](https://hackmd.io/PHZRjtQMRi2v9Z-u6bD6Tg)
[教學筆記 04:文件圖表表達方式的經驗分享](https://hackmd.io/xVM9lnFBSneA6uhIzdkYyA)
[教學筆記 05:以 C 語言開發資料庫存取程式 (ECPG)](https://hackmd.io/4jh_5A51TfieovVipQqoXA)
[推薦書籍](https://hackmd.io/t7T5FxfmT3Kih-b7PRUZrA)
[補充教材](https://hackmd.io/w-BNpl_TSuysG4_qaGtmFg)
---
## 一、建立 Linux 指令使用環境
- [ ] 1. 裝 Linux 作業系統 (含VM)
- [x] 2. 使用本案乙測環境的 Greenplum Server / Trinity Server
- [x] 3. 裝 git bash (on Windows)
- [ ] 4. 裝 Cygwin (on Windows)
- [ ] 5. 裝 WSL (on Windows)
- [ ] 6. 下載 UnxUtils 工具 (on Windows)
※ 一般 Windows 使用者推薦方法 3、4、5
---
## 二、基本指令
* pwd:顯示目前所在的絕對路徑
```shell script
$ pwd
/c/Users/cfchen
```
* cd:改變目前所在的路徑
```shell script
$ cd Desktop #進入Desktop目錄
$ pwd
/c/Users/cfchen/Desktop
$ cd #回到個人HOME目錄 (相當於「cd ~」、「cd $HOME」)
$ pwd
/c/Users/cfchen
```
* env:查看目前所有環境變數
```shell script
$ env
USERDOMAIN=cfchen-PC
OS=Windows_NT
COMMONPROGRAMFILES=C:\Program Files\Common Files
PROCESSOR_LEVEL=6
PSModulePath=C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\
CommonProgramW6432=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
FP_NO_HOST_CHECK=NO
LANG=C.UTF-8
MSYSTEM_CARCH=x86_64
......(下略)......
```
```shell script
$ env | grep LANG
LANG=C.UTF-8
$ env | grep CLASSPATH
CLASSPATH=.;D:\eclipse\workspace\MyProject\apache-ant-1.7.1\lib\ant.jar;D:\eclipse\workspace\MyProject\commons-cli-1.4\commons-cli-1.4.jar;D:\eclipse\workspace\MyProject\jsch-0.1.48.jar
$ env | grep ^PATH
PATH=/c/Users/cfchen/bin:/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/mingw64/bin:/usr/bin:/c/Users/cfchen/bin:/c/Program Files/AdoptOpenJDK/jdk-8.0.282.8-hotspot/bin
```
* alias:設定指令的別名
* 若使用 git batch,可在 ~/.bashrc 或 ~/.bash_profile 中進行設定。
* 若使用 Linux 作業系統,可在 ~/.bashrc 中進行設定。
```shell script
$ alias
alias ll='ls -al'
alias ls='ls -F --color=auto --show-control-chars'
alias wd='cd /d/work/FIA'
$ wd
$ pwd
/d/work/FIA
# 補充:透過 ${BASH_ALIASES} 陣列變數將 alias 作為參數
# 範例:
# 先建立一個 alias,其值為某路徑
$ alias | grep wd2
alias wd2='/d/work/FIA'
# alias 無法直接用來當作參數
$ cd wd2
bash: cd: wd2: No such file or directory
# 但透過 ${BASH_ALIASES} 陣列變數,就可以將 alias 當作參數
$ cd ${BASH_ALIASES[wd2]}
$ pwd
/d/work/FIA
# 範例:尋找當前目錄下的 csv 檔,並輸出到 ll (即 ls -al) 來查詢。
$ echo ${BASH_ALIASES[@]} # 印出 BASH_ALIASES 陣列變數中的所有元素,功能與「echo ${BASH_ALIASES[*]}」相同
ls -al cd /d/work/FIA ls -F --color=auto --show-control-chars
$ echo ${BASH_ALIASES[ll]} # 印出 ll 所代表的實際指令
ls -al
$ find . -name "*.csv" -exec ${BASH_ALIASES[ll]} {} \;
-rwxr-xr-x 1 cfchen None 0 十二 6 2017 ./test0n.csv
-rwxr-xr-x 1 cfchen None 11 十二 8 2017 ./test0t.csv
-rwxr-xr-x 1 cfchen None 32 十二 11 2017 ./test1n.csv
-rwxr-xr-x 1 cfchen None 45 十二 8 2017 ./test1t.csv
-rwxr-xr-x 1 cfchen None 308 十二 11 2017 ./test2n.csv
-rwxr-xr-x 1 cfchen None 321 十二 7 2017 ./test2t.csv
-rwxr-xr-x 1 cfchen None 321 十二 11 2017 ./testxt.csv
```
* man:線上說明文件
* git bash無此功能 (可以改用:**指令名稱 --help**)
* Linux 作業系統有
* type:顯示程式路徑 (由 $PATH 中尋找)
```shell script
$ type gcc
gcc is /c/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/gcc
$ type -a gcc
gcc is /c/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/gcc
gcc is /c/cygwin64/bin/gcc
```
---
## 三、檔案/目錄查詢指令: (檔案/目錄/權限)
| 指令 | 說明 |
| ---- | ---- |
| ls | 列出檔案清單 (只列出檔名) |
| ls -al | 列出檔案清單 (列出所有檔名,並印出詳細資訊) |
| ls -alt \| more | 列出檔案清單,依檔案修改時間排序(由新到舊),並逐頁顯示<br>※ more只能往下翻頁<br>※ 目前 git bash 沒有 more 功能,請改用 less |
| ls -altr \| less | 列出檔案清單,依檔案修改時間排序(由舊到新),並逐頁顯示<br>※ less可以上下翻頁 |
| ls -al \| grep ^d | 只列出目錄清單 |
| ls -al \| grep csv$ | 只列出「csv」結尾之檔名<br>※功能與「ls -al *csv」相同 |
參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#ls
---
## 四、檔案/目錄操作指令:
參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php
| 指令 | 說明 |
| ---- | ---- |
| cp | 複製檔案或目錄<br>語法:cp 來源檔 目標檔 |
| mv | 移動檔案與目錄,或更名<br>語法:mv 來源檔 目標檔 |
| rm | 移除檔案<br>語法:rm 檔案 |
| rm -rf | 強制且遞迴移除檔案或目錄<br>語法:rm -rf 檔案或目錄 |
| mkdir | 建立新目錄<br>語法:mkdir 目錄名稱 |
| rmdir | 刪除「空的」目錄<br>語法:rmdir 目錄名稱 |
| touch | 建立新檔或修改檔案時間<br>語法:touch 檔案 |
* chmod:改變檔案或目錄的權限 (用八進位表示法來代表權限 ==> r:4 w:2 x:1)
* 語法:chmod [-R] xyz 檔案或目錄
* 選項與參數:
* xyz : 數字類型的權限屬性,為 rwx 屬性數值的相加,x/y/z 分別為 owner/group/others 的權限。
* -R : 進行遞迴(recursive)的持續變更,亦即連同次目錄下的所有檔案都會變更
* 參考網址:http://linux.vbird.org/linux_basic/0210filepermission.php#chmod
* chown:改變檔案的擁有者
* 語法:chown [-R] 帳號名稱 檔案或目錄
* 語法:chown [-R] 帳號名稱:群組名稱 檔案或目錄
* 選項與參數:
* -R : 進行遞迴(recursive)的持續變更,亦即連同次目錄下的所有檔案都變更
* 參考網址:http://linux.vbird.org/linux_basic/0210filepermission.php#chown
* chgrp:改變檔案的群組
* 語法:chgrp [-R] 群組名稱 檔案或目錄
* 選項與參數:
* -R : 進行遞迴(recursive)的持續變更,亦即連同次目錄下的所有檔案、目錄 都更新成為這個群組之意。
* 參考網址:http://linux.vbird.org/linux_basic/0210filepermission.php#chgrp
---
## 五、檔案描述元、輸出/輸入轉向、管線:
* 檔案描述元 (File Descriptors)
執行某一指令時,一定會有三個檔案與這個指令有關係。在 Linux shell 中,這三個檔案會用一個整數來表示,我們稱為檔案描述元 (File Descriptors)。
| 名稱 | 說明 | File Descriptors |
| ---- | ---- | -------- |
| STDIN | 標準輸入 | 0 |
| STDOUT | 標準輸出 | 1 |
| STDERR | 標準錯誤輸出 | 2 |
* 輸出/輸入轉向
| 符號 | 說明 |
| ---- | ---- |
| > | 輸出轉向 |
| >> | 輸出轉向 (附加) |
| < | 輸入轉向 |
| # | 指令 | 說明 |
| --| ---- | ---- |
| 1| cmd > file | 將標準輸出導入檔案 |
| 2| cmd 1> file | 同上 |
| 3| cmd >> file | 將標準輸出附加到檔案之後 |
| 4| cmd 1>> file | 同上 |
| 5| cmd 2> file | 將標準錯誤輸出導入檔案 |
| 6| cmd 2>> file | 將標準錯誤輸出附加到檔案之後 |
| 7| cmd < file | 由檔案中讀取內容當成標準輸入 |
| 8| cmd 0< file | 同上 |
| 9| cmd 1> file1 2> file2 | 將標準輸出導入到file1,且標準錯誤輸出導入到file2 |
| 10| cmd > file1 2> file2 | 同上 |
| 11| cmd > file 2>&1 | 將標準輸出與標準錯誤輸出導入到同一檔案中 |
| 12| cmd >> file 2>&1 | 將標準輸出與標準錯誤輸出附加到同一檔案中 |
```shell script
# 有時候我們不想看到標準錯誤輸出,可以將其導向 /dev/null #
$ rm -rf tmp_dir > /dev/null 2>&1; mkdir tmp_dir
```
* 管線 (Pipeline)
Linux 中大部分的指令,都可以用檔案作為處理的介質,也大部分都可以從標準輸入(STDIN)中讀取輸入值。我們可以利用這種特性,讓許多程式的輸出變成其他程式的輸入,這種將「某程式的輸出轉向變成某程式的輸入」的做法,是由一種稱為「管線」(Pipeline)的機制所達成。
* 語法:cmd1 | cmd2 | ...
將 cmd1 的輸出資料連結到 cmd2 的輸入...以此類推。
```shell script
$ cat file | less #輸出檔案內容,並且分頁顯示
$ cat file | sort #輸出檔案內容,並且排序
$ sort file | uniq #對檔案內容進行排序,並且輸出不重複的值
```
---
## 六、資料查詢/處理指令:
* cat:印出檔案的內容
* 語法:cat 檔案1 檔案2 ...
* 選項與參數:
* -n :印出列數
* -b :印出列數 (不計算空白列)
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#cat
* more (less):印出檔案的內容,並可每頁閱讀
* more 只能往下翻頁
* less 可以上下翻頁
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#more
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#less
* head:取出檔案/資料前面幾列
* 語法:head [-n number] 檔案
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#head
```shell script
# 產生序列 1~10,但只取出前 3 列 #
$ seq 10 | head -3
1
2
3
```
* tail:取出檔案/資料後面幾列
* 語法:tail [-n number] [-f] 檔案
* 選項與參數:
* -f : 當檔案正在成長時(例如log檔),輸出所增加的內容。
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#tail
* 參考網址 :https://linuxhint.com/sed-command-to-delete-a-line/ (利用 sed 限制列數)
```shell script
# 產生序列 1~10,但只取出後 3 列 #
$ seq 10 | tail -3
8
9
10
```
* 如果要取出檔案/資料中間幾列? ==> 結合 head 與 tail
```shell script
# 產生序列 1~1000,但只取出第 601~603 列 #
$ seq 1000 | head -603 | tail -3
601
602
603
$ seq 1000 | tail -400 | head -3
601
602
603
```
* 如果「不要」取出檔案/資料前幾列?後幾列?
```shell script=
# 不取出第 1 列 (取 2~N 列) #
$ seq 5 | tail -n+2
2
3
4
5
# 不取出最後 1 列 (取 1~N-1列) #
$ seq 5 | head -n-1
1
2
3
4
```
* wc:計算檔案裡面的列數、字數、字元數
* 語法:wc [-lwm] 檔案
* 選項與參數:
* -l :印出列數
* -w :印出字數 (英文單字)
* -m :印出字元數
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#wc
```shell script
# 產生序列 2,4,6,8,...,1000,並計算筆數 #
$ seq 2 2 1000 | wc
500 500 1948
$ seq 2 2 1000 | wc -l
500
```
* grep:分析檔案中的每一列內容,若當中有我們所需要的資訊,就將該列印出
* 語法:grep [-acinvo] '搜尋字串' 檔案
* 選項與參數:
* -a :將 binary 檔案以 text 檔案的方式搜尋資料
* -c :計算找到 '搜尋字串' 的次數
* -i :忽略大小寫的不同,所以大小寫視為相同
* -n :輸出第幾列
* -v :反向選擇,亦即顯示出沒有 '搜尋字串' 內容的那一行
* -o :僅列印出符合搜尋字串的部分
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#grep
* 【應用實例】Trinity Decoder + Regular Expression --> 程式碼品質管理制度。
```shell script
# 產生序列 1~50,取出數字中有 0 的 #
$ seq 50 | grep 0
10
20
30
40
50
# 產生序列 1~50,取出數字中不含 2~8 的 #
$ seq 50 | grep -v [2-8]
1
9
10
11
19
# 產生序列 1~50,取出數字為 5 開頭的 #
$ seq 50 | grep ^5
5
50
# 產生序列 1~50,取出數字為 9 結尾的 #
$ seq 50 | grep 9$
9
19
29
39
49
# 只列出目錄清單
$ ls -al | grep ^d
# 利用作業一的資料集 (下載:https://data.gov.tw/dataset/8355 )
# 找出所有「臺北市」的資料:
$ grep "臺北市" 8355.csv
2010,臺北市(Taipei City),164988,11655609954340,7115920545739,2246351110702,855771119711,1437640684350,99098220195,72775434842
2011,臺北市(Taipei City),167653,12163329809495,7493852428587,2316904340647,898202307119,1454240880040,102745610225,77387387579
2012,臺北市(Taipei City),170744,11919483513103,7562067682497,2183535147387,941534418304,1231551629607,101056813365,72488269402
2013,臺北市(Taipei City),173819,12058583782802,7711309282999,2209514369483,1041575123869,1095315637909,109963704927,67796384109
2014,臺北市(Taipei City),177899,12853462046481,8118659924524,2230937138751,1096429765948,1213701692172,128279585053,68245273882
2015,臺北市(Taipei City),182517,12465638326463,8071756625341,2091143638211,1118255119287,1184475629159,141330077594,59647343575
2016,臺北市(Taipei City),186220,12063519560310,7905146270308,1886443346412,977837497831,1222970886083,140988898158,51532820406
2017,臺北市(Taipei City),189965,12418125142973,8220427315333,1984925545837,1082783201286,1129117114195,144789241656,53372837362
2018,臺北市(Taipei City),193424,13081180006541,8603735949350,2055116511218,1151854754058,1270447562753,151066973273,56262153146
2019,臺北市(Taipei City),195736,13403192015313,8825927383860,2005407123013,1263834596392,1308367451511,158798125087,53110156940
2020,臺北市(Taipei City),196897,13672656761171,9152177840748,1897947463677,1313685509984,1308845946762,170324427435,52898866537
```
| 練習1 |
| ---- |
| 一、請先至網址下載資料:https://data.gov.tw/dataset/8355<br>二、利用 shell 指令解決下列問題:<br>(1).請問這個檔案總共有幾列資料?<br>(2).請取出檔案中,年度屬於2019年的資料列(不要合計) |
* cut:
* 語法1:cut -c 字元區間
* 適用於以「固定長度」區分欄位的資料格式
* 語法2:cut -d '分隔字元' -f 指定欄位
* 適用於以「分隔符號」區分欄位的資料格式
* 範例1:取出檔案中每列位置 x1~x2 的內容
* 語法:cut -c x1-x2 檔案
* 範例2:取出檔案中每列位置 x1~x2 與 x3~x4 的內容
* 語法:cut -c x1-x2,x3-x4 檔案
* 範例3:以逗號分隔,取出檔案中每列的第 2 欄
* 語法:cut -d , -f 2 檔案
* 範例4:以逗號分隔,取出檔案中每列的第 1,3,4 欄
* 語法:cut -d , -f 1,3-4 檔案
* 範例5:以逗號分隔,取出檔案中每列的第 1,3-4 欄,輸出時以"||"分隔欄位
* 語法:cut -d , -f 1,3-4 --output-delimiter="||" 檔案
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#cut
```shell script
# 範例1:取位置第 1~4 碼(年度)之資料 #
$ cut -c 1-4 8355.csv | tail -3
2020
2020
2020
# 範例2:取位置第 1~4 碼(年度), 6~14 碼(縣市別) 之資料 #
$ cut -c 1-4,6-14 8355.csv | tail -3
2020臺東縣
2020花蓮縣
2020澎湖縣
# 範例3:以逗號分隔,取出檔案中每列的第 2 欄 #
$ cut -d , -f 2 8355.csv | tail -3
臺東縣(Taitung County)
花蓮縣(Hualien County)
澎湖縣(Penghu County)
# 範例4:以逗號分隔,取出檔案中每列的第 1,3,4 欄 #
$ cut -d , -f 1,3-4 8355.csv | tail -3
2020,5406,72612405514
2020,10336,186887750438
2020,2731,32775116184
# 範例5:以逗號分隔,取出檔案中每列的第 1,3-4 欄,輸出時以"||"分隔欄位 #
$ cut -d , -f 1,3-4 --output-delimiter="||" 8355.csv | tail -3
2020||5406||72612405514
2020||10336||186887750438
2020||2731||32775116184
```
| 練習2 |
| ---- |
| 請繼續使用練習1的資料:<br>題目:請取出檔案中,屬於2019年內的所有縣市英文名稱(不要合計) |
* sort:將資料進行排序
* 語法:sort [-bfnrtuk] 檔案
* 選項與參數:
* -b :參數忽略空白
* -f :比較文字時,不分大小寫
* -u :將重複出現的資料刪除,只留下一筆
* -r :以反向方式排序
* -t :指定欄位的分隔字元(預設為空白或tab)
* -k :指定欄位的編號 (sort -t, -k2,3 file)
* -n :讓資料根據實際數值的大小來排序(但須該欄皆為數字)
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#sort
* 參考網址:https://blog.gtwang.org/linux/linux-sort-command-tutorial-and-examples/
* uniq:取得不重複(或重複)的資料
* 語法:uniq [-idDuc] 檔案
* 選項與參數:
* -i :忽略大小寫字元的不同
* -d :只輸出重複文字列(重複列只留下一筆)
* -D :只輸出重複文字列(重複列維持原狀)
* -u :只輸出沒有重複的文字行
* -c :刪除重複文字行之後,標示出每一行的重複次數
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#uniq
* 參考網址:https://blog.gtwang.org/linux/linux-uniq-command-tutorial/
```shell script
$ seq 1 5 > seq1
$ seq 3 7 > seq2
$ cat seq1 seq2 | sort | uniq -d > seq.dup
$ cat seq.dup
3
4
5
$ cat seq1 seq.dup | sort | uniq -u
1
2
$ cat seq2 seq.dup | sort | uniq -u
6
7
```
| 練習3 |
| ---- |
| 請繼續使用練習1的資料:<br>題目:請比較 2010 年與 2011 年的縣市別有什麼差異? (何者相同?何者不同?) |
| 練習4 |
| ---- |
| 一、本題請先進入乙測 Linux 主機。<br>二、~/.bash_history 是 Linux 作業系統中用來隨時儲存歷史指令的檔案。<br>三、題目:請利用 ~/.bash_history 找出在最近使用的 Linux 指令中,最常被使用的 10 個指令與其次數,並以次數做降冪排序 (只統計指令名稱而不含後面的參數,例如:「ls -al \| grep ^d」則視為 ls 指令就好)<br> ※ 提示:<br>(1).先將 ~/.bash_history 複製到新的檔案(避免檔案一直被更新) <br>(2).先找出第一欄(指令名稱)<br>(3).排序<br>(4).計算次數<br>(5).依據次數+指令名稱再重新排序 |
* diff:比對兩個檔案之間的差異
* 語法:diff [-bBi] 檔案1 檔案2
* 選項與參數:
* -b :忽略一行當中,僅有多個空白的差異(例如 "about me" 與 "about me" 視為相同
* -B :忽略空白行的差異。
* -i :忽略大小寫的不同。
* 參考網址:http://linux.vbird.org/linux_basic/0330regularex.php#diff
* 實例可參考 DDL generator 工具所產生的比對結果檔。
```shell script
$ seq 1 5 > seq1
$ seq 3 7 > seq2
$ diff seq1 seq2
1,2d0
< 1
< 2
5a4,5
> 6
> 7
```
* tr:用來替換文字,或是刪除資料中的文字
* 語法:tr [-ds]... SET1 [SET2]
* 選項與參數:
* -d :刪除訊息當中的 SET1 這個字串
* -s :取代掉重複的字元(只取代一次)
* 參考網址:http://linux.vbird.org/linux_basic/0320bash.php#tr
```shell script
$ seq 8 12 | tr -d 1 #產生序列 8~12,並刪除有 1 的字元
8
9
0
2
$ seq 60 10 100 | tr -s 0 X #產生序列 60, 70, ..., 100,並將 0 轉為 X
6X
7X
8X
9X
1X
# 注意:使用「tr -d ' '」指令會將資料內的空白都全部刪除。
# 如果只要刪除字串前後的空白,應該改用 sed 工具。
$ echo ' 1 2 3 ' | tr -d ' '
123
$ echo ' 1 2 3 ' | sed 's/^ *//g' | sed 's/ *$//g'
1 2 3
# tr 指令也能幫忙將DOS文件轉換為UNIX/Linux文件
$ cat file | tr -d '\r'
$ dos2unix file #同上
$ unix2dos file #將UNIX/Linux文件轉換為DOS文件
```
* od:閱讀非純文字檔 (或將文字轉為非純文字)
* 範例:將一段文字,以16進位、且每個位元分開顯示。
echo -n "Hello" | od -A n -t x1
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#od
* 參考網址:https://stackoverflow.com/questions/6791798/convert-string-to-hexadecimal-on-command-line/6791875
```shell script
$ echo -n "Hello" | od -A n -t x1
48 65 6c 6c 6f
```
---
## 七、vi 編輯器基本操作:
* 參考網址:http://linux.vbird.org/linux_basic/0310vi.php

```shell script
搜尋:
於一般指令模式按「/」,輸入「\"」 (搜尋雙引號)
取代:
於一般指令模式按「:」,輸入「%s/,/|/g」(將,變成|)
刪除:
於一般指令模式按「:」,輸入「%s/\"//g」(刪除雙引號)
```
---
## 八、psql / pg_dump 工具介紹 (登入操作/匯出資料操作)
* **psql**:psql is the PostgreSQL interactive terminal.
* 選項與參數:
* -U :database user name
* -h :database server host
* -d :database name
* -p :database server port (default: "5432")
* -c :run only single command (SQL or internal) and exit
* -t :print rows only
* -A :unaligned table output mode
* -F :field separator for unaligned output (default: "|")
* 財稅案甲正環境 Greemplum:
1. 執行 psql 程式,輸入密碼再進入,然後在裡面查詢與操作:
語法:```psql -U ap_sbd -h 10.168.2.1 -d dwfdc```
2. 直接在 shell 中利用 psql 工具匯出資料 (輸入密碼後,將查詢結果輸出至螢幕):
語法:```psql -U ap_sbd -h 10.168.2.1 -d dwfdc -c "SQL語法"```
* 財稅案乙測環境 Greemplum:
1. 執行 psql 程式,輸入密碼再進入,然後在裡面查詢與操作:
語法:```psql -d dwfdc```
2. 直接在 shell 中利用 psql 工具匯出資料 (輸入密碼後,將查詢結果輸出至螢幕):
語法:```psql -d dwfdc -c "SQL語法"```
* **pg_dump**:pg_dump dumps a database as a text file or to other formats.
* 選項與參數:
* -U:connect as specified database user
* -d:database to dump
* -x:do not dump privileges (grant/revoke)
* -s:dump only the schema, no data
* -t:dump the named table(s) only (可使用萬用字元,例如 sbd_bamt\* 表示所有 sbd_bamt 開頭的表格)
* 財稅案乙測環境 Greemplum:
語法:```pg_dump dwfdc -x -s -t [schema].[table_name]```
* 於個人筆電的 PostgreSQL 中練習:
* 先在 PostgreSQL 中建立資料庫:mydb,並於其中建立 schema:stage。
* 練習之前,請先下載SQL,並在自己的資料庫中執行:https://drive.google.com/file/d/1Vf8tm8E7rk8ZqNjbKTqTNk4MxCpJNhHN/view?usp=sharing
* 可先在環境變數中設定密碼:PGPASSWORD=xxx。
1. 進入 psql 工具中,就可以開始輸入欲查詢的 SQL:
```shell script
$ psql -h 127.0.0.1 -U postgres -d mydb -p 5432
或
$ psql -h 127.0.0.1 -U postgres -d mydb
# 進入之後,設定預設尋找的 schema 為 stage:
set search_path = stage;
# 顯示目前預設的 schema:
show search_path;
```
2. 直接在 shell 中利用 psql 工具匯出資料:
```shell script
$ psql -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage"
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" > file
```
3. 尋找表格第 2 欄的內容:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -16 | tail -14 | cut -d '|' -f 2
```
4. 尋找表格第 2 欄的內容,並去除前後空白:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -16 | tail -14 | cut -d '|' -f 2 | tr -d ' '
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -16 | tail -14 | cut -d '|' -f 2 | sed 's/^ *//g' | sed 's/ *$//g'
```
5. 尋找表格第 2 欄名稱:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -1 | cut -d '|' -f 2
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -1 | awk -F '|' '{print $2}'
```
6. 尋找表格有幾欄:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -c "select * from stage.sbd_bamt001_stage" | head -1 | awk -F '|' '{print NF}'
```
7. 控制輸出格式 (不輸出表頭,且以逗號分隔):
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage"
```
8. 控制輸出格式,並尋找表格第 2 欄的內容:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 2
```
9. 控制輸出格式,並找表格第 2 欄名稱:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -A -F , -c "select * from stage.sbd_bamt001_stage" | head -1 | cut -d , -f 2
```
10. 控制輸出格式,並尋找表格有幾欄:
```shell script
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -A -F , -c "select * from stage.sbd_bamt001_stage" | head -1 | awk -F ',' '{print NF}'
```
11. 尋找特定證號格式的資料:
在本專案中,對於證號的格式有一定的規範,例如:
| 類型 | 定義 | where clause in PostgreSQL | grep in Linux |
| -------- | -------- | -------- | -------- |
| 1 | 長度為10,第1碼為大小寫英文字母,第2碼為1,2,第3~10碼為數字 (例如:個人身分證號) | ```~ '^[a-zA-Z][12][0-9]{8}$'``` | ```grep '^[a-zA-Z][12][0-9]\{8\}$'``` |
| 2 | 長度為10,第1 ~ 10碼皆為數字 (例如:大陸人士證號) | ```~ '^[0-9]{10}$'``` | ```grep '^[0-9]\{10\}$'``` |
| 3 | 長度為7,第1 ~ 7碼皆為數字 (例如:大陸人士證號) | ```~ '^[0-9]{7}$'``` | ```grep '^[0-9]\{7\}$'``` |
| 4 | 長度為10,第1碼為大小寫英文字母,第2碼為A,B,C,D,第3 ~ 10碼為數字 (例如:新版外僑證號) | ```~ '^[a-zA-Z][ABCD][0-9]{8}$'``` | ```grep '^[a-zA-Z][ABCD][0-9]\{8\}$'``` |
| 5 | 長度為10,第1 ~ 8碼為數字,第9 ~ 10碼為大小寫英文字母 (例如:舊版外僑證號) | ```~ '^[0-9]{8}[a-zA-Z]{2}$'``` | ```grep '^[0-9]\{8\}[a-zA-Z]\{2\}$'``` |
| 6 | 長度為10,第1碼為大小寫英文字母,第2碼為8,9,第3 ~ 10碼為數字 | ```~ '^[a-zA-Z][89][0-9]{8}$'``` | ```grep '^[a-zA-Z][89][0-9]\{8\}$'``` |
| 7 | 長度為8,第1 ~ 8碼皆為數字 (例如:公司營利事業登記證) | ```~ '^[0-9]{8}$'``` | ```grep '^[0-9]\{8\}$'``` |
* 下面以類型 1 為例,尋找 stage.sbd_bamt001_stage 表格的 resp_idn 欄位 (第 21 欄) 中,格式符合「長度為10,第1碼為大小寫英文字母,第2碼為1,2,第3~10碼為數字」的資料:
```shell script
# 在 SQL 中利用 where 條件來尋找
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select resp_idn from stage.sbd_bamt001_stage where resp_idn ~ '^[a-zA-Z][12][0-9]{8}$'"
A123456789
B246813579
# 在 Linux shell 中利用 grep 指令來尋找 (如果資料來源為檔案,也可以用這個方法)
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[a-zA-Z][12][0-9]\{8\}$'
A123456789
B246813579
```
12. 利用 pg_dump 匯出 stage.sbd_bamt001_stage 的 DDL (不含資料):
```shell script
$ pg_dump -U postgres -d mydb -x -s -t stage.sbd_bamt001_stage
```
| 練習5 |
| ---- |
| 請利用 psql + Linux shell 練習下面的題目:<br>在 stage.sbd_bamt001_stage 中,<br>1. 第 60 欄的欄位名稱為何?<br>2. 印出第 64 欄的欄位名稱、所有內容。<br>3. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 2 的資料內容。<br>4. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 3 的資料內容。<br>5. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 4 的資料內容。<br>6. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 5 的資料內容。<br>7. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 6 的資料內容。<br>8. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 7 的資料內容。<br>9. 利用 pg_dump 匯出 stage.sbd_bamt001_stage 的 DDL 與資料。 |
---
## 九、其他主題與工具
* find
* 用來搜尋符合特定條件的檔案。
* 語法:find [PATH] [option] [action]
* 參考網址:http://linux.vbird.org/linux_basic/0220filemanager.php#find
```shell script
# 範例:尋找當前目錄下(含子目錄)的所有 txt 檔
$ find . -name '*.txt'
./a.txt
./b.txt
./dir/c.txt
./dir/d.txt
# 範例:尋找當前目錄下(含子目錄)的所有 txt 檔,找到之後使用 ls -al 指令查詢
$ find . -name '*.txt' -exec ls -al {} \;
-rw-r--r-- 1 cfchen 197121 0 Jan 3 00:42 ./a.txt
-rw-r--r-- 1 cfchen 197121 0 Jan 3 00:42 ./b.txt
-rw-r--r-- 1 cfchen 197121 0 Jan 3 00:43 ./dir/c.txt
-rw-r--r-- 1 cfchen 197121 0 Jan 3 00:43 ./dir/d.txt
```
* ssh
* 用來登入遠端主機進行操作;或者是不登入,直接發送指令過去遠端主機。
* 參考網址:http://linux.vbird.org/linux_server/0310telnetssh.php#ssh
* 範例1:請遠端主機刪除某檔案
```ssh account@IP_address "rm -rf /path/file"```
* 範例2:呼叫遠端主機的某支 shell script
```ssh account@IP_address "/path/cmd.sh"```
* sftp
* 從遠端伺服器下載或上傳檔案
* 參考網址:http://linux.vbird.org/linux_server/0310telnetssh.php#sftp
```shell script
# 範例1:手動連線
$ sftp cfchen@localhost
cfchen@localhost's password:
Connected to localhost.
sftp> pwd
Remote working directory: /c/Users/cfchen
sftp> lpwd
Local working directory: /c/Users/cfchen
sftp> cd /c/Users/cfchen/sftp/from
sftp> lcd /c/Users/cfchen/sftp/to
sftp> pwd
Remote working directory: /c/Users/cfchen/sftp/from
sftp> lpwd
Local working directory: /c/Users/cfchen/sftp/to
sftp> ls
a.txt b.txt dir
sftp> get -r *
Fetching /c/Users/cfchen/sftp/from/a.txt to a.txt
Fetching /c/Users/cfchen/sftp/from/b.txt to b.txt
Fetching /c/Users/cfchen/sftp/from/dir/ to dir
Retrieving /c/Users/cfchen/sftp/from/dir
sftp> lls
a.txt b.txt dir
sftp> bye
# 範例2:寫成 shell script (可直接於終端機畫面輸入,或寫成 shell script 檔案再執行皆可)
sftp cfchen@localhost <<END! 1>>sftp.log 2>>sftp.log
pwd
lpwd
cd /c/Users/cfchen/sftp/from
lcd /c/Users/cfchen/sftp/to
pwd
lpwd
ls
get -r *
lls
bye
END!
# 範例3:寫成設定檔 (config file) 再執行 (但本方法僅能在使用金鑰連線的SFTP模式下才能使用)
$ cat sftp.conf
pwd
lpwd
cd /c/Users/cfchen/sftp/from
lcd /c/Users/cfchen/sftp/to
pwd
lpwd
ls
get -r *
lls
bye
$ sftp -b sftp.conf cfchen@localhost 1>>sftp.log 2>>sftp.log
```
* date
* 顯示或計算日期/時間
* 語法:date [OPTION]... [+FORMAT]
```shell script
# 顯示目前日期 (西元格式 YYYYMMDD)
$ date '+%Y%m%d'
20211227
# 顯示目前日期 (西元格式 YYYY/MM/DD)
$ date '+%Y/%m/%d'
2021/12/27
# 顯示目前日期時間 (西元格式 YYYYMMDD hhmmss)
$ date '+%Y%m%d %H%M%S'
20211227 141112
# 顯示目前日期時間 (西元格式 YYYY/MM/DD hh:mm:ss)
$ date '+%Y/%m/%d %H:%M:%S'
2021/12/27 14:12:46
# 顯示目前日期的 1 日之前 (西元格式 YYYYMMDD)
$ date -d '-1 days' '+%Y%m%d'
20211226
# 顯示目前日期的 2 日之後 (西元格式 YYYYMMDD)
$ date -d '+2 days' '+%Y%m%d'
20211229
# 顯示目前日期的 1 月之前 (西元格式 YYYYMMDD)
$ date -d '-1 months' '+%Y%m%d'
20211127
# 顯示目前日期的 1 年之前 (西元格式 YYYYMMDD)
$ date -d '-1 years' '+%Y%m%d'
20201227
# 顯示 2021/01/01 的 10 天之前 (西元格式 YYYYMMDD)
$ date -d "20210101 -10 days" '+%Y%m%d'
20201222
# 顯示上個月月底 (西元格式 YYYYMMDD)
$ date -d "`date '+%Y%m01'`-1 days" '+%Y%m%d'
20211130
# 顯示本月月底 (西元格式 YYYYMMDD)
$ date -d "`date '+%Y%m01'`+1 months -1 days" '+%Y%m%d'
20211231
# 顯示目前民國日期 (民國格式 YYYMMDD)
$ expr `date '+%Y%m%d'` - 19110000
1101227
# 顯示目前日期的 1 日之前 (民國格式 YYYMMDD)
$ expr `date -d '-1 days' '+%Y%m%d'` - 19110000
1101226
```
* time
* 當執行程式時,只要在指令前加上 time,就能計算該程式的執行時間。
* real: 從開始到結束的總時間
* user: CPU所花費的運算總時間
* sys: CPU所花費的在系統(kernel)相關的時間 比如說配置記憶體
```shell script
$ time sleep 3
real 0m3.116s
user 0m0.000s
sys 0m0.061s
```
* iconv
* 功能:編碼轉換。
* 語法1:iconv [OPTION...] [-f ENCODING] [-t ENCODING] [INPUTFILE...]
* 語法2:iconv -l
* 選項與參數:
* -l :list the supported encodings
* -f :the encoding of the input
* -t :the encoding of the output
* -c :discard unconvertible characters
```shell script
# BIG-5 轉 UTF-8
$ iconv -f BIG-5 -t UTF-8 big5.txt > utf8.txt
# UTF-8 轉 BIG-5
$ iconv -f UTF-8 -t BIG-5 utf8.txt > big5.txt
```
| 練習6 |
| ---- |
| 1. 利用 iconv 工具,將練習1的檔案 (8355.csv) 編碼由 UTF-8 改為 BIG-5,再由 BIG-5 改回 UTF-8。 (下載連結:https://data.gov.tw/dataset/8355 )<br>2. 切換一下視窗的編碼設定,確認兩種檔案是否都能順利顯示於螢幕。 |
* nohup
* 當執行程式時,只要在指令前加上 nohup,就可以讓程式避免因連線中斷而停止。
* 使用時通常會將該程式設定於背景執行 (在指令的最後面加上「&」)
* 因為 nohup 在運作時,可能不會輸出結果到螢幕 (因為程式於背景執行),所以會需要一個檔案來承接程式的輸出訊息,如果我們沒有指定這個檔案的話,nohup 會預設將訊息寫到 nohup.out 檔案裡去。
```shell script
$ nohup ls -al & # 輸出檔預設為 nohup.out
[1] 104
nohup: ignoring input and appending output to 'nohup.out'
$ nohup ls -al > result & # 輸出檔為 result
[1] 20656
nohup: ignoring input and redirecting stderr to stdout
```
* ps
* 顯示目前的程序 (process)。
* 選項與參數:
* -e :所有的 process 均顯示出來。
* -u :顯示該使用者相關的 process。
* -f :更完整的輸出。
* 參考網址:http://linux.vbird.org/linux_basic/0440processcontrol.php#ps
```shell script
# 顯示目前所有 process
$ ps -ef
UID PID PPID TTY STIME COMMAND
cfchen 19876 16984 pty0 17:36:32 /usr/bin/ps
cfchen 16984 14552 pty0 11:47:48 /usr/bin/bash
cfchen 14552 1 ? 11:47:47 /usr/bin/mintty
```
* kill
* 刪除程序 (process)
* 選項與參數:
* -9 :強制刪除 process。
* 參考網址:http://linux.vbird.org/linux_basic/0440processcontrol.php#killjobs
```shell script
# 範例:開啟兩個 git bash 視窗
# 先在第 1 個視窗輸入:
$ sleep 100 #暫停 100 秒
# 然後在第 2 個視窗輸入:
$ ps -ef # 查詢得知上述 sleep 指令所代表的 PID 為 17960
UID PID PPID TTY STIME COMMAND
cfchen 17960 16984 pty0 17:39:31 /usr/bin/sleep
cfchen 16984 14552 pty0 11:47:48 /usr/bin/bash
cfchen 17560 19208 pty1 17:37:47 /usr/bin/bash
cfchen 19208 1 ? 17:37:47 /usr/bin/mintty
cfchen 1524 17560 pty1 17:39:59 /usr/bin/ps
cfchen 14552 1 ? 11:47:47 /usr/bin/mintty
$ kill 17960 # 接著刪除 sleep 指令的 process
```
* 單引號 (```'```)、雙引號 (```"```)的差異
| 字元 | 功能 |
| -------- | -------- |
| 單引號<br>(Single quote) | 所有夾在單引號之間的字元都會失去它們的特殊涵義 |
| 雙引號<br>(Double quote) | 大部分夾在單引號之間的字元會失去它們原先的特殊涵義,除了下列類型以外:<br>(1). ```$``` 符號 (作為變數替換)<br>(2). 作為指令替換的反引號(``` ` ```)<br>(3). ```\$``` (代表 ```$``` 本身)<br>(4). ``` \` ``` (代表 ``` ` ``` 本身)(反引號)<br>(5). ```\"``` (代表 ```"``` 本身)(雙引號)<br>(6). ```\\``` (代表 ```\``` 本身) |
| 倒斜線<br>(Backslash) | 任何接在倒斜線之後的字元,會失去該字元原先的特殊涵義 |
* 反引號 (``` ` ```)
* 用來做指令代換。
* 可以容易地使用指令輸出,指定給 shell script 的變數。
* 語法:``` `cmd` ```
```shell script
# 範例1:產生一個檔名具有目前日期的檔案
$ DATE=`date '+%Y%m%d'`
$ touch filename.${DATE}.txt
$ ls -al filename*
-rw-r--r-- 1 cfchen 197121 0 Dec 27 20:01 filename.20211227.txt
# 範例2:產生一個檔名具有筆數的檔案
$ COUNT=`psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select count(*) from stage.sbd_bamt001_stage"`
$ psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" > sbd_bamt001_stage_${COUNT}.txt
$ ls -al sbd_bamt001_stage_*
-rw-r--r-- 1 cfchen 197121 10730 Jan 3 11:47 sbd_bamt001_stage_14.txt
# 小觀念:設定變數時,變數前面不用加 $,讀取時才要加 $ (讀取時有沒有加 {} 都可以)
$ MY_VAR=12345
$ echo ${MY_VAR}
12345
$ echo $MY_VAR
12345
```
| 練習7 |
| ---- |
| 一、請先至網址下載資料:https://data.gov.tw/dataset/120711 <br>(下載 csv 檔,並另存檔名為「cov19.csv」)。 <br>二、利用 shell 指令解決下列問題:<br>(1).請問這個檔案總共有幾列資料?(包含表頭與內容)<br>(2).請取出檔案中,屬於境外移入的資料列 (若為境外移入時,「縣市」與「鄉鎮」必為空值,「是否為境外移入」必為是)。<br>(3).請取出檔案中,縣市鄉鎮欄位為新北市永和區的資料列。<br>(4).請問至今有多少個縣市鄉鎮曾經有出現確定病例數? (請先排除表頭與境外移入)<br>(5).請問至今為止的累計確定病例數。<br>※ 提示:利用 awk 指令協助數字的累計。<br>※ 語法:```awk -F ',' '{sum+=$8;} END{print sum;}'```<br>(6).請問至今為止,境外移入的累計確定病例數。<br>(7).請問至今為止,本土的累計確定病例數 (本土 = 非境外移入)。<br>(8).請問2021年5月期間,新北市永和區的累計確定病例數。<br>(9).請依照各縣市鄉鎮為單位,計算其累計確定病例數,並由高至低降冪排序。<br>※提示:利用 awk 指令做群組的累計。<br>※語法:```awk -F ',' '{sum[$3" "$4]+=$8} END{for(key in sum) print key, sum[key];}'```<br> |
---
## 作業四
* **作業檢討時間:預訂於 2022/01/21 (五)。**

* 請開發一個乙測環境 Trinity 原始碼備份工具 (作為異地備援)
* 設計方法:
* 需要使用時,先由個人電腦/筆電以 putty 工具連線至乙測 Trinity Server (192.168.32.107),並執行備份程式 (backup_work.sh)。
* 備份程式會做以下的工作:
* 匯出 Trinity Job 原始碼備份檔,檔名為 [Category]_yyyymmdd.gz。
* 請每個 Category 分別產生一個 gz 檔。須備份的 Category 包含:BASE_INIT, BASE, MULTI_TAX_INIT, MULTI_TAX, STAGE_INIT, STAGE, STS_INIT, STS, UT_BASE_INIT, UT_BASE, UT_MULTI_TAX_INIT, UT_MULTI_TAX, UT_STAGE_INIT, UT_STAGE, UT_STS_INIT, UT_STS。
* sftp 至乙測 Greemplum Server (192.168.32.104),並上傳備份檔 (密碼用手動輸入)。
* 記錄執行資訊於log檔案中,包含:**執行起始日期時間、執行結束日期時間、備份檔名、本次備份檔案數量 (即 gz 檔的總數量)**。
* 備份程式 (backup_work.sh) 請放置於乙測 Trinity Server 的「/home/trinity/homework4/個人目錄」路徑中。
* 備份檔案請放置於乙測 Greemplum Server 的「/home/gpadmin/homework4/個人目錄」路徑中。
* Trinity 原始碼匯出功能:
* 參考文件「Trinity V4.1 JFDesigner User Guide.pdf」(p.102),參考章節:Import/Export Util 使用說明。
* 指令使用方式:
* 語法:java -jar /home/trinity/tool/ImportExportCMD-4.1.1.244.jar -export -host 192.168.32.107 -port 18087 -u [帳號] -pwd [密碼] -b [business entity] -c [category]
* 參數:
* -host:uiap service ip address (default:127.0.0.1)
* -port:uiap service port (default:19001)
* -u:trinity user id
* -pwd:trinity user password
* -b:business entity name
* -c:category name
* 對於非本專案,無法進入乙測環境之成員,請自行建立 Linux主機練習 (找家澤設定):

* shell script 參考範例:https://drive.google.com/file/d/1a4zxSYe_9QsVK2hBv5FEF07TvD5Eit8R/view?usp=sharing
---
## 練習解答
* 練習1(解答):
```wc -l 8355.csv```
```grep ^2019 8355.csv | grep -v "合 計"```
* 練習2(解答):
```grep ^2019 8355.csv | grep -v "合 計" | cut -d, -f2 | cut -d'(' -f2 | cut -d')' -f1```
```grep ^2019 8355.csv | grep -o "(.*)" | grep -v Total #但會包含括號```
```grep ^2019 8355.csv | grep -o "(.*)" | grep -v Total | tr -d '(' | tr -d ')'```
* 練習3(解答):
```grep ^2010 8355.csv | grep -v "合 計" | cut -d , -f 2 > 2010.txt```
```grep ^2011 8355.csv | grep -v "合 計" | cut -d , -f 2 > 2011.txt```
```sort 2010.txt 2011.txt | uniq -d > dup #共同```
```cat 2010.txt dup | sort | uniq -u #only 2010```
```cat 2011.txt dup | sort | uniq -u #only 2011```
* 練習4(解答):
```cut -d ' ' -f 1 .bash_history_new | sort | uniq -c | sort -n -k1,2 -r | head -10```
說明:1.找出第一欄(指令名稱) 2.排序 3.計算次數 4.依據次數+指令名稱再重新排序 5.取出前面10筆)
* 練習5(解答):
1. 第 60 欄的欄位名稱為何?
```psql.exe -h 127.0.0.1 -U postgres -d mydb -A -F , -c "select * from stage.sbd_bamt001_stage" | head -1 | cut -d , -f 60```
2. 印出第 64 欄的欄位名稱、所有內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 64```
3. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 2 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[0-9]\{10\}$'```
4. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 3 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[0-9]\{7\}$'```
5. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 4 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[a-zA-Z][ABCD][0-9]\{8\}$'```
6. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 5 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[0-9]\{8\}[a-zA-Z]\{2\}$'```
7. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 6 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[a-zA-Z][89][0-9]\{8\}$'```
8. 請篩選出 resp_idn 欄位 (第 21 欄) 中,格式符合類型 7 的資料內容。
```psql.exe -h 127.0.0.1 -U postgres -d mydb -t -A -F , -c "select * from stage.sbd_bamt001_stage" | cut -d , -f 21 | grep '^[0-9]\{8\}$'```
9. 利用 pg_dump 匯出 stage.sbd_bamt001_stage 的 DDL 與資料。
```pg_dump -U postgres -d mydb -x -t stage.sbd_bamt001_stage # 不要寫 -s```
* 練習6(解答):
```iconv -c -f UTF-8 -t BIG-5 8355.csv > 8355_big5.csv```
```iconv -c -f BIG-5 -t UTF-8 8355_big5.csv > 8355_utf8.csv```
* 練習7(解答):
1. 請問這個檔案總共有幾列資料?
* ```wc -l cov19.csv```
2. 請取出檔案中,屬於境外移入的資料列。
* ```grep "空值" cov19.csv > 境外移入.txt```
* ```awk -F ',' '{if($6=="是") print $0}' cov19.csv > 境外移入.txt```
3. 請取出檔案中,縣市鄉鎮欄位為新北市永和區的資料列。
* ```grep "新北市,永和區" cov19.csv > 新北市永和區.txt```
* ```awk -F ',' '{if($3=="新北市" && $4=="永和區") print $0}' cov19.csv > 新北市永和區.txt```
4. 請問至今有多少個縣市鄉鎮曾經有出現確定病例數? (請先排除表頭與境外移入)
* ```tail -n+2 cov19.csv | grep -v "空值" | cut -d , -f 3,4 | sort | uniq | wc -l```
5. 請問至今為止的累計確定病例數。
* ```awk -F ',' '{sum+=$8;} END{print sum;}' cov19.csv```
* ```tail -n+2 cov19.csv | awk -F ',' '{sum+=$8;} END{print sum;}'```
6. 請問至今為止,境外移入的累計確定病例數。
* ```tail -n+2 cov19.csv | grep "空值" | awk -F ',' '{sum+=$8;} END{print sum;}'```
* ```awk -F ',' '{if($6=="是") print $0}' cov19.csv | awk -F ',' '{sum+=$8;} END{print sum;}'```
7. 請問至今為止,本土的累計確定病例數。
* ```tail -n+2 cov19.csv | grep -v "空值" | awk -F ',' '{sum+=$8;} END{print sum;}'```
* ```awk -F ',' '{if($6=="否") print $0}' cov19.csv | awk -F ',' '{sum+=$8;} END{print sum;}'```
8. 請問2021年5月期間,新北市永和區的累計確定病例數。
* ```grep "新北市,永和區" cov19.csv | grep "2021/05" | awk -F ',' '{sum+=$8;} END{print sum;}'```
* ```awk -F ',' '{if($3=="新北市" && $4=="永和區" && substr($2,1,7)=="2021/05") print $0}' cov19.csv | awk -F ',' '{sum+=$8;} END{print sum;}'```
9. 請依照各縣市鄉鎮為單位,計算其累計確定病例數,並由高至低降冪排序。
* ```tail -n+2 cov19.csv | awk -F ',' '{sum[$3" "$4]+=$8} END{for(key in sum) print key, sum[key];}' | sort -n -r -k3```
---
* 補充1:date 日期計算功能 (如上)
* 補充2:Git bash 提供的工具:**bash.exe**
* 位置:C:\Program Files\Git\bin\bash.exe
* 功能:協助在 Windows 作業系統中執行 shell 檔案。
* 語法:bash.exe [欲執行的shell檔案] [參數1] [參數2] ...
* 補充3:crontab
* 功能:例行性工作排程工具。 (git bash 無此功能)
* 語法:crontab [-l|-e|-r]
* 選項與參數:
* -e :編輯 crontab 的工作內容。
* -l :查閱 crontab 的工作內容。
* -r :移除所有的 crontab 的工作內容,若僅要移除一項,請用 -e 去編輯。
* 參考網址:https://linux.vbird.org/linux_basic/centos7/0430cron.php#cron
```shell script
# 範例:在每天的凌晨 1:00 執行 /home/trinity/backup_work.sh 作業
$ crontab -e
# 此時會進入 vi 的編輯畫面,每項工作都是一列
0 1 * * * /home/trinity/backup_work.sh
$ crontab -l
0 1 * * * /home/trinity/backup_work.sh
```
* 補充4:簡略查詢一下在彙總表SDM文件中,有哪些格式為「#XXXX#」的變數名稱?
```grep -o '#.*#' file | sort | uniq -c```
---