ShellScript: rs (reshape) コマンドを用いてpdfの表を手軽に整形する.


要約

rsコマンドは行方向だけでなく縦方向に文字列を並べることができる.崩れた表の整形などに利用できる.

はじめに

 web上のpdfの記事中(論文など)の表を,コピーアンドペーストで適当なテキストエディタに貼り付け,編集したいことがある.貼り付けた際,表の形にならないことがよくある[6].貼り付けた際に見られる文字列は,元の表の行方向の文字が並んでいたり,列方向の文字が並んでいたり,あるいは混在することがある.こういった場合,rsコマンドを利用し,行方向・列方向に文字列を並べ替えて,表の形に整形できる.

環境

  • macOS: 10.15.4
  • zsh: 5.7.1

準備

rsコマンドについて.

  • manに "reshape a data array" とあるように,データ配列を変形するコマンドである.
  • 文字列を行方向だけでなく列方向にも並べることができる.
  • -Tオプションで転置もできる[7][8].
  • Macでははじめからインストールされている.
  • Ubuntuなどでは初めからはインストールされていない[1][2].
  • オプションでかなり応用がきく(マニュアル参照(日本語訳と英語)[3][4]).
rsの使い方
- 特に指定がない場合,行方向に要素を並べていく.
- `-t`で列方向に要素を並べる.
- `-c`で入力の区切り文字指定.例えば`-c,`はカンマで区切られる.
- `-C`で出力の区切り文字指定.`-C`のみの場合はタブ区切り.
- `-e`で行全体を1つの要素とみる.
- 2行3列にしたい場合は`rs 2 3`.
- 3列(行指定なし)の場合は`rs r 3` ()rではなくrowやそれ以外でもうまくいく.
- 2行(列指定なし)の場合は`rs 2 c` ()cではなくcolumnやそれ以外でもうまくいく.

文字列を並べる方向に関する用語について.

  • row major orderは "行方向",column major orderは "列方向" と言うことにする[9].

テストデータ

  • 以下のpdfデータの検査所見 table1を用いる([5]症例 免疫抑制下に間質性肺炎急性増悪をきたし COVID-19 感染の診断が困難であった一例)

  • マウスで範囲を選択しコピーアンドペーストする.

  • ペーストした結果が以下(表の形になっていない).

  • デスクトップ上にtest.txtとして保存する.

  • もとの表で空白セルがあると,rsコマンドでうまく並べることができない.今回は練習なので,空白セルがある場合,適当な文字(アンダースコア_など)で手作業で埋める.

  • そのほか不都合な行などがある場合,手作業で削除する.

test.txt,貼り付け後.表の形になっていない.
AST ALT LDH γ-GTP 尿素窒素 Cr
Na
K
CRP WBC Hb
PLT Baso Eosino Neutro Lympho Mono
IU/L IU/L IU/L IU/L mg/dL mg/dL mEq/L mEq/L mg/dL /μL g/dL 万/μL %
% % % %
23
19 165 74 13.5 0.83 135 3.7 0.399 7,700 13.4 19.9
42
23 460
37.4 1.35 141 4.3 15.198 8,500 15.3 21.5 0.1 0 87.4 6 6.5
26
13 395 83 15.4 0.88 138 3.9 19.724 5,700 13.4 20.3 0.2 0.4 82.4 11.2 5.8
25
13 393 78 12.8 0.91 136 4 18.032 6,300 13.5 22.2 0.2 1.1 86.3 7.7 4.7
24
14 453 58 34.7 0.98 134 4.6 7.289 15.900 11.9 18.3 0.1 0 93.3 4.1 2.5

方法,結果

  • 縦方向に並べ,17行にすればよさそうである.
  • '入院8日前`空白が5つあるのでそこをアンダースコア'_'で埋める(手作業).
  • また'1日目'の4行目も空白なので'_'で埋める.
  • 改行をLine Feed(LF, \n)に統一する.trでCarriage Return(CR)\r\nに置換する.
  • わかりやすくするために,rsコマンドで整形する前に,trコマンドで空白を改行\nに置換し,全ての要素を1列に並べる.
  • 1列にしてから,rsで整形する.-tで列方向,入力の区切り文字を指定しないときは自動的に空白-Cのみで指定しない場合,出力区切り文字は自動的にタブ17 c17行とそれにあわせた列という意味である.
trで整えてからrsコマンドで整形.
% cat test.txt | tr '\r' '\n' | tr ' ' '\n' | rs -t -C 17 c
  • 結果は以下の通り.

考察,結論

  • rsとよく似た,列を整形する代表的なコマンドとしてcolumn[11]を挙げることができる.
  • 列方向の操作できるrscolumnpastejoin,cut,awkなどと,行方向の操作が得意なgrepsedcatなどを組み合わせるとよいかもしれない[12].
  • 以下のデータでも今回と同様の操作ができる(pdfの表をコピー,テキストファイルに貼り付け,rsコマンドで整形).

[10]https://www.mhlw.go.jp/toukei/itiran/roudou/chingin/kouzou/z2018/dl/13.pdf
「平成 30 年賃金構造基本統計調査の概況」の「第1表 性別賃金、対前年増減率及び男女間賃金格差の推移」

参考

[1]https://orebibou.com/2016/07/macubuntu%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8Bbsd%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E6%95%B4%E5%BD%A2%E7%94%A8%E3%83%84%E3%83%BC%E3%83%AB%E3%80%8Ers%E3%80%8F%E3%82%B3%E3%83%9E%E3%83%B3/
Mac/Ubuntuで使えるBSDのテキスト整形用ツール『rs』コマンドを使ってみる | 俺的備忘録 〜なんかいろいろ〜
[2]https://orebibou.com/2016/07/paste%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A8rs%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/
Linux/Macのコンソール上で出力を複数列に分割する | 俺的備忘録 〜なんかいろいろ〜

[3]http://www.koganemaru.co.jp/cgi-bin/mroff.cgi?subdir=man&lc=1&cmd=&man=rs&dir=jpman-12.1.2%2Fman&sect=0
On-line Manual of "rs"
[4]https://www.freebsd.org/cgi/man.cgi?query=rs&sektion=1&apropos=0&manpath=freebsd
rs(1)
[5]http://www.kansensho.or.jp/uploads/files/topics/2019ncov/covid19_casereport_200324_2.pdf
症例 免疫抑制下に間質性肺炎急性増悪をきたし COVID-19 感染の診断が困難であった一例
[6]https://www.antenna.co.jp/pdf/reference/text-extractor.html
簡単そうで簡単ではないPDFのテキスト抽出
[7]https://stackoverflow.com/questions/58315066/bash-shell-scripting-transpose-rows-and-columns
bash shell scripting transpose rows and columns - Stack Overflow
[8]https://unix.stackexchange.com/questions/383164/how-to-transpose-a-text-file-on-character-basis
utilities - How to transpose a text file on character basis - Unix & Linux Stack Exchange
[9]https://en.wikipedia.org/wiki/Row-_and_column-major_order
Row- and column-major order - Wikipedia
[10]https://www.mhlw.go.jp/toukei/itiran/roudou/chingin/kouzou/z2018/dl/13.pdf
「平成 30 年賃金構造基本統計調査の概況」
[11]https://webkaru.net/linux/column-command/
Linuxコマンド【 column 】入力を表形式に整形 - Linux入門 - Webkaru
[12]https://orangain.hatenablog.com/entry/20100916/1284631280
Linuxコマンドでテキストデータを自在に操る - orangain flavor