OKUMA SÜRESİ 01:10

`tablo` - Komut Satırı Aracı

Bu sefer kendi geliştirdiğim bir komut satırı aracından bahsetmek istiyorum: tablo.

İzlediğim bir YouTube videosunda Nushell diye değişik bir shell gördüm. Acaba benzer bir yaklaşımı bash için yapabilir miyim? dedim ve gündelik hayatta sık kullandığım bir tool çıktı ortaya. Tabiiki açık kaynaklı! yani isteyen herkes katkı yapabilir!

Kurulumu çok kolay, eğer bilgisayarınızda go kuruluysa (go 1.25.5 ya da üzeri):

go install github.com/vigo/tablo@latest

Eğer kurulu değilse homebrew ile:

brew install vigo/tablo/tablo

ile kurabilirsiniz. Ne işe yarar? ister interaktif ister pipe yöntemiyle, text’leri tabular şekilde formatlı göstermenizi ya da filtrelemenizi sağlar:

echo "hello world" | tablo
┌─────────────┐
│ hello world │
└─────────────┘

Kolon ayracı (field delimeter) olarak varsayılan karakter çift boşluk (double space) karakteridir. Eğer;

echo "hello  world" | tablo # iki ya da daha fazla boşluk
┌───────┬───────┐
│ hello │ world │
└───────┴───────┘

şeklinde olur. Eğer illa tek boşluk isterseniz;

echo "hello world" | tablo -f " "
┌───────┬───────┐
│ hello │ world │
└───────┴───────┘

Nerelerde işe yarar? Mesela $PATH değişkeni… Kocaman tek satır bir text ve : bir ayraç:

echo "${PATH}"
/Users/vigo/.bun/bin:/opt/homebrew/opt/postgresql@17/bin:/Users/vigo/.cargo/bin:/Users/vigo/.rbenv/shims:/Users/vigo/.rbenv/bin:/Users/vigo/.gem/ruby/2.6.0/bin:/Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/shims:/Users/vigo/.pyenv/libexec:/Users/vigo/.pyenv/plugins/python-build/bin:/Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/bin:/Users/vigo/.pyenv/plugins/pyenv-virtualenv/bin:/Users/vigo/.pyenv/plugins/pyenv-virtualenv/shims:/Users/vigo/.pyenv/shims:/Users/vigo/.pyenv/bin:/opt/homebrew/opt/curl/bin:/opt/homebrew/opt/sqlite/bin:/Users/vigo/.docker/bin:/opt/homebrew/opt/go/libexec/bin:/Users/vigo/.local/go/bin:/Users/vigo/.local/bin:/Users/vigo/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/pmk/env/global/bin:/Library/Apple/usr/bin:/usr/local/share/dotnet:~/.dotnet/tools:/Users/vigo/.orbstack/bin

Bunu;

echo "${PATH}" | tablo -l ":"
┌───────────────────────────────────────────────────────────────────────────────────┐
│ /Users/vigo/.bun/bin                                                              │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/opt/postgresql@17/bin                                               │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.cargo/bin                                                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.rbenv/shims                                                          │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.rbenv/bin                                                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.gem/ruby/2.6.0/bin                                                   │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/shims                          │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/libexec                                                        │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/plugins/python-build/bin                                       │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/bin                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenv/bin                                   │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenv/shims                                 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/shims                                                          │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.pyenv/bin                                                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/opt/curl/bin                                                        │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/opt/sqlite/bin                                                      │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.docker/bin                                                           │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/opt/go/libexec/bin                                                  │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.local/go/bin                                                         │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.local/bin                                                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/bin                                                                   │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/bin                                                                 │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/homebrew/sbin                                                                │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /usr/local/bin                                                                    │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /System/Cryptexes/App/usr/bin                                                     │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /usr/bin                                                                          │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /bin                                                                              │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /usr/sbin                                                                         │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /sbin                                                                             │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin         │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin               │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /opt/pmk/env/global/bin                                                           │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Library/Apple/usr/bin                                                            │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /usr/local/share/dotnet                                                           │
├───────────────────────────────────────────────────────────────────────────────────┤
│ ~/.dotnet/tools                                                                   │
├───────────────────────────────────────────────────────────────────────────────────┤
│ /Users/vigo/.orbstack/bin                                                         │
└───────────────────────────────────────────────────────────────────────────────────┘

Ya da;

echo "${PATH}" | tablo -l ":" -n
┌───────────────────────────────────────────────────────────────────────────────────┐
│ /Users/vigo/.bun/bin                                                              │
│ /opt/homebrew/opt/postgresql@17/bin                                               │
│ /Users/vigo/.cargo/bin                                                            │
│ /Users/vigo/.rbenv/shims                                                          │
│ /Users/vigo/.rbenv/bin                                                            │
│ /Users/vigo/.gem/ruby/2.6.0/bin                                                   │
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/shims                          │
│ /Users/vigo/.pyenv/libexec                                                        │
│ /Users/vigo/.pyenv/plugins/python-build/bin                                       │
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenvwrapper/bin                            │
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenv/bin                                   │
│ /Users/vigo/.pyenv/plugins/pyenv-virtualenv/shims                                 │
│ /Users/vigo/.pyenv/shims                                                          │
│ /Users/vigo/.pyenv/bin                                                            │
│ /opt/homebrew/opt/curl/bin                                                        │
│ /opt/homebrew/opt/sqlite/bin                                                      │
│ /Users/vigo/.docker/bin                                                           │
│ /opt/homebrew/opt/go/libexec/bin                                                  │
│ /Users/vigo/.local/go/bin                                                         │
│ /Users/vigo/.local/bin                                                            │
│ /Users/vigo/bin                                                                   │
│ /opt/homebrew/bin                                                                 │
│ /opt/homebrew/sbin                                                                │
│ /usr/local/bin                                                                    │
│ /System/Cryptexes/App/usr/bin                                                     │
│ /usr/bin                                                                          │
│ /bin                                                                              │
│ /usr/sbin                                                                         │
│ /sbin                                                                             │
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin         │
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin               │
│ /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin │
│ /opt/pmk/env/global/bin                                                           │
│ /Library/Apple/usr/bin                                                            │
│ /usr/local/share/dotnet                                                           │
│ ~/.dotnet/tools                                                                   │
│ /Users/vigo/.orbstack/bin                                                         │
└───────────────────────────────────────────────────────────────────────────────────┘

Yapabilirsiniz. Ben özellikle docker komutunda çok kullanıyorum:

docker images --format "{{.ID}}  {{.Repository}}  {{.Tag}}"
0668926e2d4e  postgres  17
35267b49b084  redis  latest
0eaa8705309b  rancher/local-path-provisioner  v0.0.34
227b80ee8e0a  docker/model-runner  latest
b41714cf6249  rancher/local-path-provisioner  v0.0.31
5548a49bb60b  registry.k8s.io/metrics-server/metrics-server  v0.7.2
a7f913520a4a  rancher/local-path-provisioner  v0.0.26
97e04611ad43  rancher/mirrored-coredns-coredns  1.10.1
7d46a07936af  rancher/mirrored-pause  3.6

docker images --format "{{.ID}}  {{.Repository}}  {{.Tag}}" | tablo
┌──────────────┬───────────────────────────────────────────────┬─────────┐
│ 0668926e2d4e │ postgres                                      │ 17      │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 35267b49b084 │ redis                                         │ latest  │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 0eaa8705309b │ rancher/local-path-provisioner                │ v0.0.34 │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 227b80ee8e0a │ docker/model-runner                           │ latest  │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ b41714cf6249 │ rancher/local-path-provisioner                │ v0.0.31 │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 5548a49bb60b │ registry.k8s.io/metrics-server/metrics-server │ v0.7.2  │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ a7f913520a4a │ rancher/local-path-provisioner                │ v0.0.26 │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 97e04611ad43 │ rancher/mirrored-coredns-coredns              │ 1.10.1  │
├──────────────┼───────────────────────────────────────────────┼─────────┤
│ 7d46a07936af │ rancher/mirrored-pause                        │ 3.6     │
└──────────────┴───────────────────────────────────────────────┴─────────┘

Sadece ilk ve ikinci kolonları almak için:

docker images --format "{{.ID}}  {{.Repository}}  {{.Tag}}" | tablo -fi "1,2"
┌──────────────┬───────────────────────────────────────────────┐
│ 0668926e2d4e │ postgres                                      │
├──────────────┼───────────────────────────────────────────────┤
│ 35267b49b084 │ redis                                         │
├──────────────┼───────────────────────────────────────────────┤
│ 0eaa8705309b │ rancher/local-path-provisioner                │
├──────────────┼───────────────────────────────────────────────┤
│ 227b80ee8e0a │ docker/model-runner                           │
├──────────────┼───────────────────────────────────────────────┤
│ b41714cf6249 │ rancher/local-path-provisioner                │
├──────────────┼───────────────────────────────────────────────┤
│ 5548a49bb60b │ registry.k8s.io/metrics-server/metrics-server │
├──────────────┼───────────────────────────────────────────────┤
│ a7f913520a4a │ rancher/local-path-provisioner                │
├──────────────┼───────────────────────────────────────────────┤
│ 97e04611ad43 │ rancher/mirrored-coredns-coredns              │
├──────────────┼───────────────────────────────────────────────┤
│ 7d46a07936af │ rancher/mirrored-pause                        │
└──────────────┴───────────────────────────────────────────────┘

Hatta çıktıyı json almak için:

docker images --format "{{.ID}}  {{.Repository}}  {{.Tag}}" | tablo -fi "1,2" -j

çıktı:

[
  [
    "0668926e2d4e",
    "postgres"
  ],
  [
    "35267b49b084",
    "redis"
  ],
  [
    "0eaa8705309b",
    "rancher/local-path-provisioner"
  ],
  [
    "227b80ee8e0a",
    "docker/model-runner"
  ],
  [
    "b41714cf6249",
    "rancher/local-path-provisioner"
  ],
  [
    "5548a49bb60b",
    "registry.k8s.io/metrics-server/metrics-server"
  ],
  [
    "a7f913520a4a",
    "rancher/local-path-provisioner"
  ],
  [
    "97e04611ad43",
    "rancher/mirrored-coredns-coredns"
  ],
  [
    "7d46a07936af",
    "rancher/mirrored-pause"
  ]
]

Hatta eğer jq varsa;

docker images --format "{{.ID}}  {{.Repository}}  {{.Tag}}" | tablo -fi "1,2" -j | jq

Ek olarak csv dosyları ile de uğraşıyorsanız:

# cat /path/to/file.csv | tablo -f ";"

echo 'Username;Identifier;First name;Last name
booker12;9012;Rachel;Booker
grey07;2070;Laura;Grey
johnson81;4081;Craig;Johnson
jenkins46;9346;Mary;Jenkins
smith79;5079;Jamie;Smith' | tablo -f ";"
┌───────────┬────────────┬────────────┬───────────┐
│ Username  │ Identifier │ First name │ Last name │
├───────────┼────────────┼────────────┼───────────┤
│ booker12  │ 9012       │ Rachel     │ Booker    │
├───────────┼────────────┼────────────┼───────────┤
│ grey07    │ 2070       │ Laura      │ Grey      │
├───────────┼────────────┼────────────┼───────────┤
│ johnson81 │ 4081       │ Craig      │ Johnson   │
├───────────┼────────────┼────────────┼───────────┤
│ jenkins46 │ 9346       │ Mary       │ Jenkins   │
├───────────┼────────────┼────────────┼───────────┤
│ smith79   │ 5079       │ Jamie      │ Smith     │
└───────────┴────────────┴────────────┴───────────┘

Hatta sadece Username kolonu lazımsa;

echo 'Username;Identifier;First name;Last name
booker12;9012;Rachel;Booker
grey07;2070;Laura;Grey
johnson81;4081;Craig;Johnson
jenkins46;9346;Mary;Jenkins
smith79;5079;Jamie;Smith' | tablo -f ";" Username
┌───────────┐
│ Username  │
├───────────┤
│ booker12  │
├───────────┤
│ grey07    │
├───────────┤
│ johnson81 │
├───────────┤
│ jenkins46 │
├───────────┤
│ smith79   │
└───────────┘

Hatta;

echo 'Username;Identifier;First name;Last name
booker12;9012;Rachel;Booker
grey07;2070;Laura;Grey
johnson81;4081;Craig;Johnson
jenkins46;9346;Mary;Jenkins
smith79;5079;Jamie;Smith' | tablo -nh -n -f ";" Username
┌───────────┐
│ booker12  │
│ grey07    │
│ johnson81 │
│ jenkins46 │
│ smith79   │
└───────────┘

Şeklinde de kullanabilirsiniz. İsterseniz çıktıyı bir dosya ya da > /path/to/file şeklinde atabilirsiniz:

cat /path/to/file | tablo > /path/to/out

Eğer bir input pipe’lamazsanız direk text’i girip CTRL + D ile input moddan çıkarak işlemlerinizi yapabilirsiniz:

tablo
press ENTER and CTRL+D to finish text entry
foo  bar
┌─────┬─────┐
│ foo │ bar │
└─────┴─────┘

Bir sürü opsiyonu var;

tablo -h

ile örnekleriyle birlikte görebilirsiniz.