第四堂:「Data Wrangling」

有陣子沒寫了,來還個債...

這個系列是從『MIT 的「The Missing Semester of Your CS Education」』這邊延伸出來的,這邊講的是「Data Wrangling」這篇。

這篇是在講 pipe 的用法,在講這些工具之前,其實有個很重要的概念應該要說明 (但沒有在這篇文章裡被提到),也就是 Unix philosophy,這個哲學是指 unix 環境下的工具,都會設計成只做好一件事情。

而要怎麼把這些工具串起來,最常見的就是 pipe,你可以在文章裡看到 grepsedsort 這些工具的用法,以及怎麼用 pipe 串起來。

這邊剛好也可以提一下,利用 pipe 可以把不同功能打散到不同的 process 上,剛好也可以稍微利用到現在常見的多 CPU 的環境。

另外上面因為提到了 grep,文章內花了不少篇幅在講 Regular expression 這個在 CS 課程裡面也是重要的基礎。

會放這種篇幅長度,一方面是 Regular expression 的實用性很高,另外一方面,學術上與自動機理論中的 DFANFA 都有關,算是學習計算理論的起點:

然後後面就有提到 AWK 這個工具,這邊要注意的是,雖然可以用 Perl 之類的工具作到類似的事情 (而且更強大),但 AWK 有被放到 POSIX 標準裡,所以在各種作業系統內幾乎都一定會出現,加上語法算是簡單,學起來還是很有幫助...

然後再最後面的段落冒出一個 gnuplot 畫個圖,以及示範 xargs 這種神器要怎麼用 (這邊會更建議看一下 manpage,可以配合 find 之類的工具用,並且平行化同時處理)。

然後最後示範了 binary data 怎麼處理。

comm 的用法...

最近在 Twitter 上看到不少 shell 指令的說明,這則 tweet 是講 comm 這個指令:

1 是只有第一個檔案有的內容,2 是只有第二個檔案有的內容,而 3 是兩者都有的內容,而且檔案內容需要排序過。

當你 -1 時表示幹掉 1 的部份,-2 代表幹掉 2 的部份,-3 代表幹掉 3 的部份,然後可以疊起來用... 不過平常還是用 diff 比較多,每次看到 comm 的說明都是玩過再熟悉一下,然後就丟著 XD

Windows 10 將支援 AF_UNIX (Unix Socket)

在「Unix sockets come to Windows」這邊看到微軟的說明文「AF_UNIX comes to Windows」,Windows 10 將要引入 AF_UNIX 了:

Beginning in Insider Build 17063, you’ll be able to use the unix socket (AF_UNIX) address family on Windows to communicate between Win32 processes. Unix sockets allow inter-process communication (IPC) between processes on the same machine.

所以這讓跨 process 溝通的方式又多了一種,而 Unix 的程式如果要移植到 Windows 上,至少這塊有相容... (相容性與 bug 還不知道情況 XD)

CUPS 從 GPLv2 變成 Apache License, Version 2.0 了

CUPS 是處理印表機的軟體,在 macOS 以及其他各種 Unix-like 環境下都會使用。

在「CUPS relicensed to Apache v2」這邊看到 relicense 的消息,正式的公告則是在「CUPS License Change Coming」這邊可以看到:

Apple is excited to announce that starting with CUPS 2.3 we will be providing CUPS under the terms of the Apache License, Version 2.0.

剛好 GPLv2Apache License, Version 2.0 之間不相容,這樣跳過去算是趣味趣味...

用 awk 取代 grep 的工作

在「SKIP grep, use AWK」這篇看到關於使用 awk 取代 grep 的介紹。

作者提到這樣的替換:

$ [data is generated] | grep something | awk '{print $2}'
$ [data is generated] | awk '/something/ {print $2}'

還有這樣直接替換 grep 的方式:

$ [data is generated] | awk '/something/'

以及 -v 的替換:

$ [data is generated] | awk '/something/ {next} 1'
$ [data is generated] | awk '! /something/'

不過感覺還好耶...

StackOverflow 上離開 Vim 方法的文章...

被拿出來當 PR 宣傳了:「Stack Overflow: Helping One Million Developers Exit Vim」。

由於 Vim 是 Unix-like 系統一定會內建的 editor,所以常常被拿來放在 tutorial 裡面 (考慮到普及性,但完全不熟的初學者就...),或是不小心在輸入 vipw 或是 visudo 之類的指令就中獎了:

可以看到 pageview 破一百萬次了 XDDD 而且流量也都很穩定:

依照地區來拆開的話:(不過沒有照人口數正規化...)

然後做交叉分析,看這些卡在 Vim 的人平常是看什麼其他的文章:

回到資料分析的角度來看,這些東西可以透過有 cookie 的 access log 做到。有 access log 後可以用 Google CloudBigQuery,也可以用 AWS 家的 Amazon Athena 做。

debootstrap 可以把所有檔案都裝到 /usr 下了

從「You can now try merged /usr in Debian」這邊看到,早期因為硬碟空間比較小的關係,會切成 /bin/usr/lib 之類的目錄:

The original impetus for requiring these directories was due to space limitations in the first Unix implementations, developers favoring the change point out.

這個理由很明顯已經消失了,所以 Debian 就規劃要整併起來...

Unix 程式碼演進的記錄

GitHub 上的「dspinellis/unix-history-repo」專案放進了 Unix 程式碼從 1970 年演進到 2016 年的記錄:

The history and evolution of the Unix operating system is made available as a revision management repository, covering the period from its inception in 1970 as a 2.5 thousand line kernel and 26 commands, to 2016 as a widely-used 27 million line system.

主要的目的是讓研究人員可以直接分析,減少重複的工作:

The project aims to put in the repository as much metadata as possible, allowing the automated analysis of Unix history.

後面的分支主要是以 FreeBSD 為主:(在列表的部份也可以看到)

It has been created by synthesizing with custom software 24 snapshots of systems developed at Bell Labs, the University of California at Berkeley, and the 386BSD team, two legacy repositories, and the modern repository of the open source FreeBSD system.

整個 repository 頗壯觀的 XD

MySQL 裡儲存時間的方式...

這應該是 MySQL 的 best practice 之一,不知道為什麼 Baron Schwartz 又拿出來講:「A simple rule for sane timestamps in MySQL」。

MySQL 內可以儲存「日期與時間」的資料型態是 DATETIME 與 TIMESTAMP 兩種,不過 DATETIME 沒有時區觀念,而 TIMESTAMP 只能是 UTC (GMT+0)。

相較於隔壁棚 PostgreSQLDate/Time Types 就一種 TIMESTAMP,但支援 with timezone 與 without timezone 直接解決問題。

這使得 MySQL 上在儲存「日期與時間」以及處理的時候一直有種 WTF 的感覺...

就如同 Baron Schwartz 的建議,如果使用 MySQL,目前比較好的方法是用 INT UNSIGNED NOT NULL 儲存,把 timezone 的處理都放到應用程式端來處理,這樣產生的問題會比較少...

真的需要在 INSERT 或是 UPDATE 時更新欄位,可以用 trigger 處理,彈性反而比內建功能大不少。