マルチプラットフォームな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の中でファイルをコピーしたいときなど、ちょっとしたことを実現するために、わざわざ環境ごとにコマンドを変更するのは非常に面倒です。こういう非効率は許せません。
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件を取得するときはこんな感じです。
もちろん、取得したpid
をkill
することもできます。
このように、パイプを使ってかなり直感的にコマンドを操作できるのが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型として返ってくるので、get
やfirst
などを使って必要な情報を取り出すことができます。
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=python
やhttps://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操作に憧れてるんだけどハードル高いな...と感じている方にも、シンタックスがモダンなので良い勉強になるでしょう。
ぜひお試しください!
おまけ
おいおい年越しだぜ...と思ってたらもう1年の25%が終了とのこと!ぎゃー!
株式会社マインディアでは、Flutter/Goエンジニア、Railsエンジニアを募集しております。
カジュアル面談などの場を用意しておりますので、気軽にお声がけください。
Discussion