# 【教學筆記 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 ![](https://i.imgur.com/2wNs40m.gif) ```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 (五)。** ![](https://i.imgur.com/dhfm9iG.png) * 請開發一個乙測環境 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主機練習 (找家澤設定): ![](https://i.imgur.com/IOtUdh5.png) * 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``` ---