二つのファイルの共通行(または共通しない行)を得る

例えば、サービスAでは登録されているけれどもサービスBには登録されていないユーザの一覧を得たい、という様な場合。もちろんdiffでよしなにやることもできますが、commも便利です。 例えば次の様にリストがあるとします。 サービスAのユーザーリスト(users_a.txt): alice bob charlie dave oscar サービスBのユーザーリスト(users_b.txt): charlie isaac justin mallory oscar これらに対してcommを使うと次の出力が得られます: $ comm users_a.txt users_b.txt alice bob charlie dave isaac justin mallory oscar TABで揃えられた列がそれぞれ左から、Aにだけ存在する行、Bにだけ存在する行、Cにだけ存在する行、となっています。これだけだと別にそれほど便利ではないんですが、commはそれぞれの行を非表示にする事もできます。それぞれ、非表示にしたい行を-1 -2 -3で指定します。 Aだけに存在する行を表示する: $ comm -23 users_a.txt users_b.txt alice bob dave 両方に存在する行を表示する: $ comm -12 users_a.txt users_b.txt charlie oscar diffだとdiffの後にgrepやらなんやらして必要な物を抜き出す必要があるでしょうから、これは楽ですね。 もちろん、diffの様に他のコマンドの標準出力を取ることもできます。 例えばhttps://example.com/api/users_b.txtが先ほどのusers_b.txtと同じ内容を返すとするとしてAだけに登録しているユーザーを取得したい場合 $ curl -s https://example.com/api | comm -23 users_a.txt - alice bob dave とできますし、2つのユーザーリストを返すAPIが有ったとして、共通のユーザーを一覧にしたい場合、次の様にできます: $ curl https://example1.com/users | jq . [ { "username": "alice" }, { "username": "bob" }, { "username": "charlie" }, { "username": "dave" }, { "username": "oscar" } ] $ curl https://example2....

2022-09-28 · nasa9084

bashのhere-documentは一時ファイルを作成するらしい

皆さん使ってますか、here-document。bashでいうとこういう奴: cat <<EOF this is here document EOF 出力はこう: this is here document 複数行に渡るテキストをリテラルとして表現したい場合に便利ですね。で、shellscriptからREST APIにリクエストを投げたくて、here-documentを使ってJSONをべたっとスクリプト内で書いてたんですけど、こんなエラーが出てました(パスはもちろん違いますよ。念のため。): /path/to/shellscript/using/here-document.sh: line 179: cannot create temp file for here-document: No space left on device 全然知らなかったけど、here-documentって一時ファイルを作成するんですね。確かめてみます。 $ docker run -it --rm centos:7 bash [root@8017e5e28d6e /]# yum install -y strace (中略) [root@8017e5e28d6e /]# cat <<EOF > script.sh > cat <<EOS > foo > bar > baz > EOS > EOF [root@8017e5e28d6e /]# strace -f bash script.sh |& grep tmp [pid 61] stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ....

2021-09-08 · nasa9084

dateコマンドで簡単な時間計算をする

shellscript内で時間計算をしたい事がある。例えば、「最終実行から10分経過していたらxxxをする」という様なケース。定期的にファイルを生成したい、といった簡単なユースケースであれば、findコマンドあたりでファイルの変更タイムスタンプを調べるといった方法でも実現可能ではあるけれど、「ファイルの中に記載された時間から10分経過しているかどうか調べる」なんて事もあるでしょう(あった)。 shellscriptで時間の計算するのって面倒そうなんだよな・・・と思っていたのですけれど、私のユースケースだとそれほど難しくなくて、dateコマンドで大体なんとかなるという事が分かったのでメモしておきます。 時間を比較する 二つの時間を比較したい。これは対象の時間がUnix時間で表現されていれば非常に簡単で、dateコマンドを使用する必要すら無く、test乃至[で普通に比較ができます。もちろん取り扱いは数字として取り扱うことになるので、比較演算子として-ltか-gtを使用します。 # 1626146220 = 2021-07-13T12:17 # 1626146340 = 2021-07-13T12:19 if [ 1626146220 -lt 1626146340 ]; then echo hello fi # Output: # hello 対象の時間がUnix時間で表現されていない場合、Unix時間に変換して比較するのがおそらく最も簡単です。dateコマンドで一度時間をパースして、Unix時間の形で出力します。パースには-d / --dateオプションを使用します。Unix時間として出力するためのフォーマット文字は%sです。 if [ $(date -d '2021-07-13T12:17' +%s) -lt $(date -d '2021-07-13T12:19' +%s) ] then echo hello fi # Output: # hello -d / --date オプションは一般的なフォーマットの日付文字列をよしなにパースしてくれます。詳しいフォーマットはGNU Coreutilsのマニュアル などを見ると良いでしょう。 n分前/n分後を求める 扨、ここからが本題なのですが、n分前/n分後を計算してみましょう。といっても、dateコマンドを使用すると非常に簡単に求めることが可能です。 まずは現在時刻から1時間後を求めてみましょう。-d / --dateオプションに加算したい時間を渡すだけです。 date +%R date -d '1 hour' +%R # Output: # 12:34 # 13:34 hourの他にも、yearやmonth、day、minuteなどそれっぽいモノは大体使用することができます。珍しいところだとfortnight(2週間)を使うこともできます。 単に1 hourと書くのがなんとなく気持ち悪いという人はnowやtoday、thisなどを使用してより自然言語っぽい感じで書くこともできます...

2021-07-13 · nasa9084

cut vs. parameter expansion

TL;DR:: bash/zsh parameter expansion is faster than cut. which is faster? Consider you want to take out hostname from URL or IP with port like some.mysql.server:3306 or 192.168.1.10:3306 using bash/zsh. There are some way to do this. The first way is using cut command: $ TARGET="192.168.1.10:3306" $ echo ${TARGET} | cut -d ":" -f 1 Now printed 192.168.1.10 on your screen. The second way is using “shell parameter expansion”, which is functions of bash/zsh built-in....

2018-02-26 · nasa9084