@kyanny's blog

My thoughts, my life. Views/opinions are my own.

grep -o . で横を縦に(文字数を数える)

無駄に横長の文字列があって切り詰めたいとする。

❯ cat tbl.txt
Database Name                                                                                                                    Log Size (MB)  Log Space Used (%) Status
-------------------------------------------------------------------------------------------------------------------------------- -------------- ------------------ -----------
master                                                                                                                                2.2421875          44.076656           0
tempdb                                                                                                                                71.992188          19.869778           0
model                                                                                                                                 7.9921875          9.2375364           0
msdb                                                                                                                                  9.9296875          13.965382           0

cut -c を使うわけだが、問題は長い文字列が何文字あるのかを数えるのが大変なこと。

grep -o . は任意の文字にマッチして、各文字を一行ずつ出力する。

❯ echo 'Database Name' | grep -o .
D
a
t
a
b
a
s
e

N
a
m
e

cat -n にパイプすると文字列の長さがわかる。

❯ echo 'Database Name' | grep -o . | cat -n
     1  D
     2  a
     3  t
     4  a
     5  b
     6  a
     7  s
     8  e
     9
    10  N
    11  a
    12  m
    13  e

これを利用すると、さっきの tbl.txt の無駄に長い区切り線は 128 文字だったことがわかる。

❯ awk 'NR==2{print}' tbl.txt | grep -o . | cat -n
     1  -
     2  -
     3  -
     4  -
     5  -
     6  -
     7  -
     8  -
     9  -
    10  -

(以下略)

   125  -
   126  -
   127  -
   128  -
   129
   130  -
   131  -
   132  -
   133  -

ただまあ、これなら長い文字列をコピーして irb とかで String#size を呼ぶ方が楽で早い気もする。

❯ irb
irb(main):001:0> '--------------------------------------------------------------------------------------------------------------------------------'.size
=> 128

あと、- が横に並んでるのは当たり前で見やすいが、縦に一文字ずつたくさん並んでいると割と見づらいし、空行を見つけづらい。- を別の文字列に置き換えて・・とかやり始めると無駄に複雑になるので、結局あんまり便利ではなかったかも。

そもそもやりたかった表の切り詰めは、

❯ cut -c 1-30,129- tbl.txt
Database Name                  Log Size (MB)  Log Space Used (%) Status
------------------------------ -------------- ------------------ -----------
master                              2.2421875          44.076656           0
tempdb                              71.992188          19.869778           0
model                               7.9921875          9.2375364           0
msdb                                9.9296875          13.965382           0

こういう感じになるが、1-30 の部分は Database Name 列の(区切り線以外の)最長文字列に合わせて適宜調整が必要。

本当はうまいこと自動調整して最短に切り詰めるプログラムを書こうと色々試してたのだけど、意外とスマートな方法が見つけられなくて(区切り線以外の行の余白の切り詰めが面倒)、結局 cut でぶった斬るのが早いという結論。