zaki work log

作業ログやら生活ログやらなんやら

PowerShellのワンライナーでExcelの表とMarkdownの表をサクッと変換する

宗派に反して業務上Excelで表を作らざるを得ないけど手元ではMarkdownで編集したい!残したい!というあなたへ。

ExcelMarkdown

こんな表があったとして、

f:id:zaki-hmkc:20200418085435p:plain

Excelの変換したい部分をCtrl-cでコピーして、(他にもやり方あると思うけど)以下のPowerShellコマンドレットを実行。

PS C:\Users\zaki> Get-Clipboard  | % {$_ -replace "`t", "|" -replace "^", "|"  -replace "$", "|" } | Set-Clipboard
# 当初"\s+"を"|"に`replace`してたけど、セル内にスペースある場合と空セルがある場合に失敗するので"`t"に修正

すると、クリップボード内に以下のテキストがセットされる。

|NAME|STATUS|ROLES|AGE|VERSION|
|okd4-master0|Ready|master,worker|20d|v1.17.1|
|okd4-master1|Ready|master,worker|20d|v1.17.1|
|okd4-master2|Ready|master,worker|20d|v1.17.1|
|okd4-worker1|NotReady|worker|84s|v1.17.1|
||

末尾改行分が入ってしまうのと、ヘッダ行の区切り部分がないけどこんな感じ。(そこまで処理しようとするとワンライナーの範疇超えてしまう💦)

MarkdownExcel(TSV)

Markdownで書いた表をExcelに貼り付けたいときは

| NAME         | STATUS   | ROLES         | AGE | VERSION |
| ------------ | -------- | ------------- | --- | ------- |
| okd4-master0 | Ready    | master,worker | 20d | v1.17.1 |
| okd4-master1 | Ready    | master,worker | 20d | v1.17.1 |
| okd4-master2 | Ready    | master,worker | 20d | v1.17.1 |
| okd4-worker1 | NotReady | worker        | 84s | v1.17.1 |

こんなMarkdownがあったとして、テキストをクリップボードへコピーしたら、以下のPowerShellコマンドレットを実行。

PS C:\Users\zaki> Get-Clipboard | %{$_ -replace "\s+\|\s+", "`t"  -replace "^\|\s+", ""  -replace "\s+\|$", "" } | Set-Clipboard

すると、以下のテキストがクリップボードへセットされるので、そのままExcelへペーストしてやればOK

NAME    STATUS  ROLES   AGE VERSION
------------    --------    -------------   --- -------
okd4-master0    Ready   master,worker   20d v1.17.1
okd4-master1    Ready   master,worker   20d v1.17.1
okd4-master2    Ready   master,worker   20d v1.17.1
okd4-worker1    NotReady    worker  84s v1.17.1

tabが見えないけど、こうなっている。

f:id:zaki-hmkc:20200418085714p:plain

Excelへ貼り付けるとこんな感じ。

f:id:zaki-hmkc:20200418090055p:plain

簡単に解説

項目 説明
Get-Clipboard クリップボードからデータを取り出す
Set-Cilpboard クリップボードへデータをセット
% ForEach-Objectコマンドレットのalias
-replace テキスト置換(正規表現可)
`t タブ (PowerShellはテキストエスケープが逆スラッシュじゃなくてバッククォート)
^ 正規表現で「行頭」という位置を表す(ゼロ幅)
$ 正規表現で「行末」という位置を表す(ゼロ幅)

PowerShell上のテキストのエスケープはバッククォートだけど、正規表現のメタ文字は通常通りバックスラッシュなのでいろいろ紛らわしいのがミソ。

あとGet-Clipboard ... -replaceと、foreach使わずに一気にうまいこといかなかったので、foreachで回避してる。

Cygwinの場合

クリップボードからテキストを取り出すgetclipと、クリップボードにセットするputclipcygutils-extraパッケージにあるので、sed,awk,perlなど信仰する宗教に合わせてフィルタコマンドを実行すれば同じようにできます。

% getclip | (フィルタ) | putclip

環境

PS C:\Users\zaki> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.18362.628
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.18362.628
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

worker0どこいった?