☘️

マルチプラットフォームなNu Shellを使ったら、あらゆるデータを一行で扱えて時間効率が上がった

3秒まとめ

  • マルチプラットフォームで同じコマンドを利用して手元で動かしたい処理をサクッと実行できる
  • GitHub Actionsでも簡単に利用可能
  • JSON, YAML, SQLite, CSV, EXCELなどのファイルをデフォルトでパースしてデータフレームのように扱える
  • httpリクエストも投げられるので、curl入ってない!みたいなことでイラッとすることが減る

こんな方向きの記事ではない

  • zsh, bashなどをマスターしている人にとってはあまり導入する意味がない
  • サーバールームでLinuxの標準シェル以外使えない環境で作業するような人には向かない

MacやWindows、コンテナの中を触るときにコマンドが微妙に違う

例えば、Mac,Linux系であればlsでファイル一覧を確認してcpコマンドでファイルをコピーするといった芸当が、Windowsでは普通にはできません。
これは、Windows(PowerShell)のデフォルトでこれらのコマンドがサポートされていないためです。

自分で意識してコマンドを切り替えればいいのですが、Makefileの中でファイルをコピーしたいときなど、ちょっとしたことを実現するために、わざわざ環境ごとにコマンドを変更するのは非常に面倒です。こういう非効率は許せません。

https://www.nushell.sh/

Nu Shellは、マルチプラットフォームに対応したシェルです。
コマンドの結果をデータフレームのように利用できたり、JSON, Excel, CSV, YAMLなど多様なファイルの操作やhttpリクエストを含むちょっとした処理が非常に簡単に行える便利なツールです。

fishなどに標準装備されている、各種コマンドの履歴から作られるコマンドのオートコンプリート機能なども含め、小一時間ほどいじってみたところ、結構心地よく使えたのでご紹介です。

How to Install

めっちゃ簡単です。

Mac

brew install nushell

Windows

winget install nushell

上記でインストール後に nuとするだけでnuを開くことができます。

GitHub Actions

Setupが用意されているので、3行書くだけで使えるようになります

- uses: hustcer/setup-nu@v3.9
  with:
    version: "0.80"

コマンドの出力を直感的にハンドリングできる

ls

単純にlsコマンドを打つだけでも、見やすい感じにしてくれます。

でも、実際の用途を考えると、grepで取り出したいものだけ取り出したくなることでしょう。
そんなとき、nuは、whereを使います。

whereで直感的に絞り込む

whereの使い方は非常に簡単です。例えば、カレントディレクトリの .md を検索したい時は以下のようにします。

ls | where name =~ '.md'   

たったこれだけ!

あまりCLIに慣れていない人でも、whereという単語はいくつかのプログラミング言語やライブラリにおける filterの概念を表現することが多く、非常に直感的ではないかと思います。

ファイルサイズで絞り込む

さらに、ファイル名からではなく、ファイルサイズのようなメタデータを検索することも可能です。

ls | where size > 100B    

たったこれだけ。
お気付きかもしれませんが、ここに表示されている name, type, size, modifiedそれぞれを自由にユーザー側でコントロールすることができます。

sort-byで並び替えも超簡単!

もちろん、並べ替えもできます。
sort-by [col] [--reverse]です。

ls | sort-by size --reverse | first 3  


今回は、さらにfirst 3とすることで、最初の3件のみを取得してみました。
Pandasでいうと df.head(3)のようなイメージ。

これを応用して、psコマンドで実行中のプロセス一覧を取得し、メモリ使用量の多い順に並び替えした上で最初の10件を取得するときはこんな感じです。

もちろん、取得したpidkillすることもできます。
このように、パイプを使ってかなり直感的にコマンドを操作できるのがnuの良いポイントです。

helpでサクッと使い方を確認する

他のシェルとはかなり違った書き味と感じる方もいるかもしれません。
わからなくなったらhelpコマンドの出番です。

help where

helpコマンドを利用することで、コマンドの利用方法も簡単に説明してくれるため、わざわざWebでドキュメントを開く必要もなく、簡単な処理を実行することが可能です。

ParseがすごいぞNu Shell

JSON, YAML, TOML, CSV, etc...
かなりの数のファイルをデフォルトでパースできるのが Nu Shellのもうひとつの大きな強みです。

効果を実感してもらうために、以下のような.yamlを用意してみました。

name: test_flutter
description: A new Flutter project.

publish_to: 'none'

version: 2.1.30+114

environment:
  sdk: "^3.1.5"

dependencies:
  hoge_sdk: ^4.1.0
  analyzer: ^5.3.0
  app_settings: ^5.0.0

これをnuで開くためには以下のようにします。

open test.yaml

なんだかこれだけでもかなりみやすくなったような気もしますが、nuを使えば、さらに階層構造を利用して必要な箇所のみを取って来ることが可能です。

例えば、hoge_sdkのバージョンを取得する場合はこう。

open test.yaml | get dependencies.hoge_sdk 

これでhoge_sdkに指定されている ^4.1.0を取得することが可能です。

驚くべきことに、nuを使うと、JSON, TOML, CSVなど他のフォーマットで書かれていたとしても、同じコマンドでデータを取得できます。

nuでもっと深く構造化データを探索する

私は業務でワーカーがJSONで吐き出したデータの中に、目的の値を確認するようなケースがたまにあります。

JSONは普通にVSCodeで開いたりすると、データの内容でフィルタしたりするのはひと手間かかるので、地味に面倒な作業です。

しかし、nuを使えばもっと簡単にJSONのチェックを行うことが可能です。

例えば以下のようなJSONがあったと仮定します。

[{
    "id": 1,
    "name": "name1",
    "data": {
        "value": 10,
        "amount": 100
    }
},
{
    "id": 2,
    "name": "name2",
    "data": {
        "value": 20,
        "amount": 200
    }
}]

このJSONは先ほどのYAMLと同じように openで開けます。

open test.json

ここから、name=name1のデータのみを取ってきたいときはこうできます。

open test.json | where name == 'name1'  

また、value>15を取ってきたいときはこんな感じ。

open test.json | where data.value > 15   

さらに値を足してくれるmath sumを組み合わせて、amountの合計を取得したいときはこう

 open test.json | get data.amount | math sum 

このようにnuを利用することで、よくあるこんな情報をjsonから気軽に取得できます。

  • あるフィールドの値が外れ値になっていないか確認したい
  • uidに該当するデータのみを取得したい
  • コードを書くほどでもない簡単な集計処理を手軽に実行したい

httpコマンドでcurlともオサラバできちゃうかも

curlの挙動がMacとWindowsで微妙に違うぞ...!!
おい、この端末curlはいってないじゃん...!!
などなど、とっさにcurlが使えずに萎えた経験、ないでしょうか。僕はポンコツなのであります。

ちょっとした動作確認のためにHTTPリクエストを投げたいだけなのに、curlを入れたり入れなかったり、PostmanなどのHTTPクライアントを立ち上げたり...そんなことに費やす時間も、nuで効率化することができます。

GETリクエストは http get するだけ

 http get [url]

とするだけで、GETリクエストを投げられます。

以下の例では、connpassのAPIから最新のイベント情報を1件取得しています。

 http get https://connpass.com/api/v1/event | get events | first 1

getの後に続く eventは、JSONのキーに対応します。
レスポンスは nu の table型として返ってくるので、getfirstなどを使って必要な情報を取り出すことができます。

JSONの構造をいちいち把握するのも面倒な場合は、describeを使ってテーブルの型を把握できます。

 http get https://connpass.com/api/v1/event | describe

 // response
 record<results_start: int, results_returned: int, results_available: int, events: list<any>>

POSTリクエストも簡単

 http post --content-type application/json https://www.example.com { field: value }

開発中のAPIのエンドポイントに対して、サクッとリクエストを投げたいときなんかは、これで十分ですね。
このくらいシンプルでいいんですよ。

curlでいいじゃんと言えばそれまでかもしれませんが、レスポンスを nu のテーブル型でハンドリングできることも考えると、nuを使うメリットは大きいと思います。

http post hoge | get data.name のように書けば非常に直感的にデータを処理できるのです。

複数のリクエストを投げる

複数のエンドポイントにリクエストを投げて結果を保存するのも簡単です。

connpassのAPIの場合、https://connpass.com/api/v1/event/に対して、keywordパラメータを指定することで、キーワードにマッチするイベント情報を取得できます。

nu shellは、配列を扱うこともできるので、複数キーワードを用意すれば、複数のリクエストを投げて結果を統合することが可能です。
まずは配列を扱ってみましょう。

['python', 'go'] | each {|u| echo ('https://connpass.com/api/v1/event/?keyword=' + $u )}

このコマンドでは、['python', 'go']という配列を作成し、eachでそれぞれの要素に対して、https://connpass.com/api/v1/event/?keyword=pythonhttps://connpass.com/api/v1/event/?keyword=goといったURLを生成して表示しています。

もちろん、パイプの左側を open input.json | get.languagesのように、ファイルから取得したデータを渡すよう変更してもOK。

これを使えば、複数のキーワードに対してリクエストを投げて、結果を保存することもできます。

['python', 'go'] | each {|u| http get ('https://connpass.com/api/v1/event/?keyword=' + $u | url decode) | get events} | save output_compass.json

使ってみた感想まとめ

僕も実際業務で使っていて、JSON, CSVなど、ちょっとしたファイルやデータを扱うときに、nuはとても便利でした。

grep, sedなどいろいろなLinuxのネイティブコマンドを駆使してやりゃーいいんだよ!という話もありますし、データセンターで閉じた環境でそれらをやれる技術力も重要です。

しかし、本当にちょっとしたデータの確認という点ではnuを使う方が簡潔で、素早いのは間違いないでしょう。僕はこれらの確認にかける時間をできるだけ節約し、メインの業務に使う時間を最大化することでプロダクトに貢献したいと考えているので、nuはとても適しているように感じました。

家ではWindows、社内ではMacを使っていたり、コンテナに入ったら当然Linuxを使うことになるので、マルチプラットフォームしているnuを使うと切り替えコストも低くできることもメリットです。

高級言語に慣れていて、CLI操作に憧れてるんだけどハードル高いな...と感じている方にも、シンタックスがモダンなので良い勉強になるでしょう。

ぜひお試しください!

おまけ

https://twitter.com/hagakun_yakuzai

おいおい年越しだぜ...と思ってたらもう1年の25%が終了とのこと!ぎゃー!

株式会社マインディアでは、Flutter/Goエンジニア、Railsエンジニアを募集しております。
カジュアル面談などの場を用意しておりますので、気軽にお声がけください。

引き続き、業務中に興味が湧いた記事にしていきますので、良かったらZennTwitterのフォローをお願いします!

株式会社マインディア テックブログ

Discussion