diffで差分の行を'> 'をつけずにそのまま表示するにはold-line-format、new-line-format、unchanged-line-formatを使う

ログファイルに欠損があって「新しいファイルにだけある行を表示したいなぁ」というよくある要望がでまして。


今までは

diff old new | perl -nle 's/> // and print $_'

みたいなことして表示してたんだけど「きっともっと楽な方法あるよね」と思いman diffしてみることに。
comm使えばできるけどsortしなくちゃなのでやめました)


んで、new-line-formatというのを見つけたのだけど、これをやっても「新しい行全て」が表示されてしまい「あれれー!」となる。

--new-line-format=FORMAT
       if-then-else 形式で、 2 番目のファイルだけにある行の出力に FORMAT を用いる。


最後の方まで読むと例が書いてあって"unchanged-line-formatも一緒に使えば良い"ということがわかりました。

--unchanged-line-format=FORMAT
       if-then-else 形式で、両方のファイルに共通な行の出力に FORMAT を用いる。


つまり、以下のように「new-lineを%Lで改行あり表示しつつ、変更してないやつは''で非表示にして握りつぶす」とやれば良い。

diff --new-line-format='%L' --unchanged-line-format='' old new


もし、oldの方の差分もあって一緒に出したいなら、

diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' a.txt b.txt

とやれば良いですね。

% cat a.txt
1
2
3
4
5

% cat b.txt
2
4
6

% diff a.txt b.txt
1d0
< 1
3d1
< 3
5c3
< 5
---
> 6

% diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' a.txt b.txt
1
3
5
6

【解決済】gitで、あるコミット時のソースコードを、ちらっとlessとかで見たい場合のコマンドって、なにかしら?diffはいらないの。

2013-12-20 15:02 追記

速攻で解決した。インターネット素晴らしい。


元記事

という発言があって、twitterで以下のやり取りをしました。



「確かに一時的にgit coでファイル取り出すことあるけどもっと楽な方法あるのかなぁ?」と探したもののググる力が足りず、最後にgistで書いた以下のような力技になりました。



ただ、適当実装だし、再発明してる感じもするので既にあるなら知りたいところ。
どうすると良いんでしょうか?

会議室名がオシャレ過ぎて覚えられない君へ #vgadvent2013

f:id:lesamoureuses:20131213202642j:plain

この記事はVOYAGE GROUP エンジニアブログ : Advent Calendar 2013の14日目の記事になります。
ちょっとハマってて気が付いたら日付が変わってました。


さて、去年のAdvent Calendarは社内図書館のOASISの本の整理の話を書いたので、「今年も会社の話で何かないかなぁ」とネタを探してました。

会議室の名前と場所が覚えられない


はじめに会議室の地図の写真を載せましたが弊社、会議室の名前がオシャレ過ぎて覚えられません。
どのくらい覚えにくいのかを理解できるようにいくつか紹介します。


まず、いつも #ajiting で飲んでるAJITOは大丈夫。デカいし入口だし覚えやすいです。
f:id:lesamoureuses:20131213235814j:plain


畳があるジパング。ふむ、これはまだ覚えやすい。
f:id:lesamoureuses:20131213235628j:plain


段ボール素材のアトランティス。こっからもうキツいですね。これはもう「段ボール部屋」と呼んじゃってます。
f:id:lesamoureuses:20131213235707j:plain


レムリア。「糸がたくさんの部屋」みたいな感じで呼ぶ。
f:id:lesamoureuses:20131214012137j:plain


ユーラシア。「何かアノすごく茂ってる所」
f:id:lesamoureuses:20131213235728j:plain


こんな感じでいろんな会議室があるんですが、とにかく名前から場所を思い出すのがつらいわけです。
(わかりづらいが故に僕らは会議室の場所をひねり出すため脳内メモリにあった仕事用記憶を一回スワップ領域に追い出すだなんていう煩わしい作業をしなければならないわけですよ!!!!)

覚えられないなら覚えなければ良い


ということで、覚えなくて済むようにAcme::VOYAGEGROUP::ConferenceRoomというモジュールを作りました。


インストールはcpanmでサクッと。

cpanm Acme::VOYAGEGROUP::ConferenceRoom


インストールするとconference_roomというコマンドが使えるようになるので引数に会議室の名前を入れるだけです。


たとえばzipang。
f:id:lesamoureuses:20131215030718p:plain
おぉ!わかりやすいですね!


次にajito。赤くなってるのが大変わかりやすくて良いですね!
f:id:lesamoureuses:20131215030829p:plain


大文字の方がしっくりくるってこともあるので大文字にも対応しました。
f:id:lesamoureuses:20131215030939p:plain


「まぁでも普段カタカナ使うよね」ってこともあるかもなのでカタカナも。
f:id:lesamoureuses:20131215031008p:plain


せっかくだからひらがなも。
f:id:lesamoureuses:20131215031049p:plain


「うーん、どうせだったら出力はJSONがいいなぁ」と言われる可能性も考えて第2引数にjsonと渡すことでjson出力できるようにもしました。
f:id:lesamoureuses:20131215031206p:plain


これで昨日覚えたjqでもアクセスできますね!!!
f:id:lesamoureuses:20131215032355p:plain


「jsonあるならXMLもあるべきなんじゃないの?」ってことでXMLも。
f:id:lesamoureuses:20131215032534p:plain


最後に「せっかくだからMessagePackでのデータのやりとりも考えるべきなのでは?」ということでMessagePackにも対応しました。
f:id:lesamoureuses:20131215032718p:plain



以上です!
Acme::VOYAGEGROUP::ConferenceRoom、総じて便利ですね!!!これでもう会議室の場所を覚える必要はありません!!!

まとめ

  • 本エントリでは弊社の会議室名のオシャレさについて言及しました。
  • ギリギリになって書き始めるとハマって日付が変わるということについて言及しました。


明日はアラビア語の学習環境を整えることで著名@hagino3000 さんです!もしかするとアラビア語でのpostになるかもしれませんね!

正規表現のx修飾子を使い、かつ、"ム"を指定するとTest::MinimumVersionでrequires 5.017009になる

2014-01-03 追記

これ、PPIx::Regexpのせいだった。
「ム」を16進数表示すると\x{E3}\x{83}\x{A0}になり、この最後のA0がWhitespeceと見なされてx修飾子と一緒になると

'perl_version_introduced' => '5.017009'

となる。
https://rt.cpan.org/Ticket/Display.html?id=91798

(でも、そもそもx修飾子使ってた所でsyntax変わらないからversionは元のままでいいんじゃないかな?)
x修飾子の動きが変わったのは5.17.9だからperl_version_introducedとしては合ってるのか。

元記事

5.8で動くようなコードでminil distを実行したらなぜかrequires 5.017009のエラーが出て「えー!何でー!」となりハマりました。


試しに5.17.9のperldeltaを見てみたんですが、そこに関わるようなコードを書いてなさそうで良くわからなくて断念。


とりあえずどんどんコード削除していった結果、最小の再現コードが作れました。

「ム」と「x修飾子」を使うと起こる。

で、もう一度5.17.9のperldelta見た感じ、ここの部分に当たるんじゃないかなと推測。
ただ「/xの空白の話だし、ムはU+30E0だからここかどうかは確実じゃないなぁ」とも思いまして。


ここでふとCompiler::Lexer をつかって Perl::MinimumVersion::Fast をかいてみた - blog.64p.orgを思い出して、Test::MinimumVersion::Fastを使って試してみたらエラーになりませんでした。


ここまでわかった所でその後どうしていいかわからないのでとりあえずメモ。


正規表現のx修飾子を使い、かつ、"ム"を指定するとTest::MinimumVersionでrequ ...

tmuxでanyenv(*env)で*env/shimsがsystemのPATHより前に読まれてsystemが使われてしまう対処

anyenvを使っているんですが、

/usr/local/heroku/bin
/Users/monmon/.anyenv/envs/rbenv/bin
/Users/monmon/.anyenv/envs/plenv/bin
/Users/monmon/.anyenv/envs/rbenv/shims
/Users/monmon/.anyenv/envs/plenv/shims
/Users/monmon/.anyenv/bin
/Users/monmon/local/bin
/Users/monmon/bin
/usr/local/sbin
/usr/local/bin
/usr/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin

のようなPATHがtmuxを起動すると

/usr/local/heroku/bin
/Users/monmon/.anyenv/envs/rbenv/bin
/Users/monmon/.anyenv/envs/plenv/bin
/Users/monmon/.anyenv/bin
/Users/monmon/local/bin
/Users/monmon/bin
/usr/local/sbin
/usr/local/bin
/usr/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
/usr/local/heroku/bin
/Users/monmon/.anyenv/envs/rbenv/bin
/Users/monmon/.anyenv/envs/plenv/bin
/Users/monmon/.anyenv/bin
/Users/monmon/local/bin
/Users/monmon/bin
/usr/local/sbin
/Users/monmon/.anyenv/envs/rbenv/shims
/Users/monmon/.anyenv/envs/plenv/shims

のようになってshimsが

/usr/local/bin
/usr/bin

より前に読まれてしまい、plenvのperlではなくsystemのperlが使われてしまいます(typeset -U path PATHはしてない状態)。


で、自分の環境だけの話なのかなぁと思ったら
http://konboi.hatenablog.com/entry/2013/12/12/213931
みたいなのも見つけて

rbenv works by inserting a directory of shims at the front of your PATH:
~/.rbenv/shims:/usr/local/bin:/usr/bin:/bin


Understanding Shims

ってのも見て「どうしたらいいんだろう?」と中身見てみた。


結果、anyenvだけの話ではないのだけど、~/.anyenv/libexec/anyenv-init内の

102   echo "$(${ENV_ROOT}/bin/${env} init -)"

の所で、初めに実行された時には

export PATH=/Users/monmon/.anyenv/envs/plenv/shims:/Users/monmon/.anyenv/bin:/Users/monmon/local/bin:/Users/monmon/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

なんですが、tmuxを起動した時にもう一度実行された時には

source /Users/monmon/.anyenv/envs/plenv/libexec/../completions/plenv.zsh

になるので、shimsをPATHに入れるタイミングが初めにしかなく、shimsがsystemより前になってしまう。


ということで、結果的に良いか分からないけど、shimsをPATHで読み込むようにしました。

-  ANYENV_ADD_PATH="${ENV_ROOT}/bin:${ANYENV_ADD_PATH}"
+  ANYENV_ADD_PATH="${ENV_ROOT}/bin:${ENV_ROOT}/shims:${ANYENV_ADD_PATH}"

https://github.com/monmon/anyenv/commit/5e976cd66904b8e4771f1aca8ed4b32ab43de80d


こうすることで、tmux使ってない場合には

/Users/monmon/.anyenv/envs/rbenv/bin
/Users/monmon/.anyenv/envs/rbenv/shims
/Users/monmon/.anyenv/envs/plenv/bin
/Users/monmon/.anyenv/envs/plenv/shims
/Users/monmon/.anyenv/envs/rbenv/shims
/Users/monmon/.anyenv/envs/plenv/shims

となってしまって良いのか悪いのかわからないけど、僕はtypeset -U path PATHでPATHの重複消しているのでいいかなと思いました。
これ、anyenvだけの問題ではないと思うのでもっといい解決方法あるんじゃないかなと思ったんだけど探せませんでした。

「Minillaをインストールしようと思ったらテストが通らない!><」と思ったら~/.gitignoreのせいでした

家でサクッとインストールできたはずなのに会社で以下のようなエラーが出て「あれー!」となりました。

===(      49;1  0/?  0/?  1/? )=========================================Use of uninitialized value in string eq at /Users/no-kumagai/.cpanm/work/1386851499.15174/Minilla-v0.11.0/blib/lib/Minilla/ReleaseTest.pm line 49.

        #   Failed test at t/filegatherer.t line 32.
        #          got: '.gitmodules,META.json,README,foo,libfoo/foo.c'
        #     expected: '.dot/dot,.gitignore,.gitmodules,META.json,README,foo,libfoo/foo.c,xtra/.dot,xtra/.dotdir/dot'
        # Looks like you failed 1 test of 1.

    #   Failed test 'include_dotfiles'
    #   at t/filegatherer.t line 33.
Use of uninitialized value in string eq at /Users/no-kumagai/.cpanm/work/1386851499.15174/Minilla-v0.11.0/blib/lib/Minilla/ReleaseTest.pm line 49.
===(      50;2  0/?  0/?  2/? )=========================================    # Looks like you failed 1 test of 3.

#   Failed test 'FileGatherer'
#   at t/filegatherer.t line 45.
# Looks like you failed 1 test of 2.
t/filegatherer.t ................... Dubious, test returned 1 (wstat 256, 0x100)

で、コケた結果見たらわかるとおり.(ドットファイル)でこけてる。
単純に~/.gitignoreに

.*

が入ってたからだけでした(ドットファイルはとりあえず弾いて必要なやつだけ追加できるようにする派です)。

idobata.ioでGeneric HookでFAILUREとかSUCCESSを出す

こんにちはmonmonです。
みんなが大好きグループチャットのIdobata
JenkinsのHookが使えたりして便利ですが、cronとかでも失敗した時の
f:id:lesamoureuses:20131028212008p:plain
や成功した時の
f:id:lesamoureuses:20131028212018p:plain
を出したいなって思ったりしますよね。


ということでGeneric Hookを使って出しましょう。


まず失敗。

<span class="label label-important">FAILURE</span>

こんな感じでlabelとlabel-importantのclassを指定したHTMLをidobataさんに飛ばすだけです。


次に成功。

<span class="label label-success">SUCCESS</span>

こんな感じで今度はlabel-successのclassを指定すれば良いです。


ということで、
f:id:lesamoureuses:20131028213228p:plain
って感じや
f:id:lesamoureuses:20131028212747p:plain
って感じの通知をidobataさんに出すことができます。


簡単ですね!