ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Rubyコミュの一行野郎

  • mixiチェック
  • このエントリーをはてなブックマークに追加
awk(違)は書かねぇ、たった一行。というわけで、主にRubyを中心としたワンライナーのトピックです。

コメント(33)

>metanest さん
トピック立てていただいてありがとうございます。
話を振ってみたものの自分で新しいトピ立てるのはためらっていたので(汗)


取り合えず(簡単なモノですが)、いくつか手土産代わりに(^^;;

1> ruby -ne 'print $_ if /RE/ =~ $_' hoge.txt         # grep相当
2> ruby -rkconv -ne 'puts Kconv.toutf8($_)' hoge.txt    # nkf -w 相当
3> ruby -ne 'END{ print $.}' hoge.txt               # wc -l 相当

初心者質問トピックで教えていただいた、はなおかさん作
4> ruby -e 'print readlines.reverse.join' hoge.txt       # GNU tac 相当 || BSD tail -r 相当

コマンドラインオプションの -n と、-a, -F あたりをうまく使いこなせると、awkっぽい
一行野郎が作れそう。。。

require 'win32ole' して四苦八苦するよりも、-F でデリミタをカンマ(,) にして
ExcelにCSV出力させたほうが、快適に仕事が終わるんじゃないかなぁ・・・(^^;
もうちょっとダケ実用的なものを(^^;;:

ruby -ne 'print if %r(#{Time.now.strftime "%d/%b/%Y"}) =~ $_' /var/log/httpd/access.log

apache のアクセスログから、今日のアクセスのみを抽出。
もうちょっとエレガントになりますかねぇ??
Perl風で、スクリプト中では使いませんが、ワンライナーと言うことなら、$_ を活用して、

ruby -ne 'print if /RE/' # grep

あと、joinしなくても

ruby -e 'puts readlines.reverse' # tac

-s オプションで、gawk の -v オプションのようなことが出来ないかと思いましたが、-e とは併用できないみたいです。

ALPHAです。こんにちは。

in message 2 I wrote:
>require 'win32ole' して四苦八苦するよりも、-F でデリミタをカンマ(,) にして
>ExcelにCSV出力させたほうが、快適に仕事が終わるんじゃないかなぁ・・・(^^;

で、やってみました。ここまで来るとほとんどパラノイアですが(自爆)
# 確かにコマンドラインから動きますけど6ステップもあるんじゃ『一行野郎』とは
# ちょっと呼べないかも(汗)

ruby -anpF, -e "BEGIN{puts'<table>'};t=($.==1)?'th':'td';$_='<tr>';$F.each{|f|$_<<%Q(<#{t}>#{f}</#{t}>)};$_<<%Q(</tr>\n);END{puts'</table>'}" hoge.csv > hoge.htm

Basicで一行にどれだけ詰め込めるか没頭していた若い頃を思い出してしまって(^^;;
ALPHAです、こんにちは。なんかトピックを私物化しつつある気もしますが(^^;;

ruby -e "def f(x) return x<1 ? 1 : x*f(x-1) end; p f 10"

ワンライナーでも、ちゃんとリカーシブコールできますね。
だれかハノイの塔でもチャレンジしてみませんか?(汗)
一応可能ですが...

ruby -e 'def move(from, to); p "move #{from} ==> #{to}"; end; def hanoi(n, from, to); if n <= 1 then move(from, to) else other = 6 - (from + to); hanoi(n - 1, from, other); move(from, to); hanoi(n - 1, other, to); end; end; hanoi(4, 1, 3)'

単に改行をセミコロンにして並べただけですなw (ゴルファーの能力がないとも言う)
>metanestさん

私も考えてみましたが、、、
・if文を三項演算子に
・moveメソッドは展開
・other変数の代入もやめて展開
くらいで、基本アルゴリズムは一緒でした(^^;
・n-1段をotherへ
・n段目をfrom からtoへ
・n-1段をotherからtoへ
という3ステップは、もうちょっとひねらないとですかねぇ。。。
# && とか || の特徴(Perlで言うところのread or die)lをうまく使えないか考えてみたんですが

>ruby -e "def hanoi(n, from, to) (n>1)?(hanoi(n-1, from, 6-from-to); p (%Q[move #{from} ==> #{to}]); hanoi(n-1, 6-from-to, to)):(p %Q[move #{from} ==> #{to}]) end; hanoi 4, 1, 3"

相変わらず、Windows + cmd.exe で動作確認してるのでダブルクォーツでくくってますが(^^;


-- 別件

ちょいとした作業をしていて
>perl とある文法チェッカ | grep -v 'いらない行' | awk '$2 ~ /RE/ { print }'
# REは注目したいエラーコード。事前にgrep -vしてるのは、いっぱいでるウォーニングを
# 篩にかけたかったから。
というコトをしたかったのですが、あいにくとそのマシンにgrepもawkもない(^^;;

で、
>perl とある文法チェッカ | sed -e '/いらない行/d' | ruby -anF\x20 -e 'print if /RE/ =~ $F[1]'

で、事なきを得たんですが。
あとから考えてみると
>perl とある文法チェッカ | ruby -anF\s+ -e 'next if /いらない行/; print if /RE/ =~ $F.[1]'
のほうがよかったかなぁ・・・・

ちなみに(コミュの主旨から外れますが)、もしrubyも入っていなかったら
>perl とある文法チェッカ | sed -e '/いらない行/d' | sed -ne '/^[^ *] RE.*$/p'
だったでしょうか?
# ruby が入っていない環境でも、awk もgrep もなくてもsed は入れるヒトですので(^^;
# sed ってアレだけのコマンドしかなくてもチューリング完全なんですよね。。。

ruby くらいの能力があると単体でなんでもこなせてしまいますが、パイプを使って
> foo | ruby -e 'hogehoge' | hugahuga
なんて使い方も一行野郎っぽいかもしれないですね。
# さしあたり、grep, sed, sort, wc, sort, uniq, tail あたりでしょうか?全てruby単体で
# こなせる作業ばかりですが
tacコマンド相当、こんなもんでどうですかね?
プロゴルファーならもっと縮めてくると思いますが。

ruby -ne 'x||="";x[0, 0]=$_;END{print x}'
ruby -ne 'x||="";x[0,0]=$_;END{puts x}'

冗長な空白を削ってprintのかわりにputsを使ってちょっと短縮
> otnさん
$ ruby -s -e 'p $foo' -- -foo=bar
"bar"
--でruby自身へのオプションとスクリプト(ここでは-e)への引数を分ける必要があります。
スクリプトファイルを指定する場合はそこでruby自身のオプションは終わりとみなされますが、-eは複数指定できるので終わりを明示しなければなりません。
こんにちは。
識者の方の添削希望します。

仕様は…
1. あるフォルダ配下の .txt ファイルを総なめ
2. ファイル中の文字を grep し、そのファイル名を表示
3. ファイルは EUC で書かれている。実行OSは UTF-8

以下のようになったのですが、我ながらダサいです。
find . -name \*.txt | ruby -rnkf -ne 'buf = File.read($_.chomp); p $_.chomp if NKF.nkf("-w", buf) =~ /ほげ/'
>11 tana さん

識者じゃなくて、Sunday Programmerのヘタレで申し訳ないです。
その上、ご希望の環境が手元に作れなかったので、Windows 上に
ファイル名はWindowsネイティブ(Windows-31J)で、中身EUC のファイルを
作って確認しました。

Ruby 1.9からは多言語化実装であるM17N (正確には多 *言語* ではなく多 *字*でしょうけど)
が取り入れられ、文字エンコーディングまわりが大きく変更されています。

参考記事
http://jp.rubyist.net/magazine/?0025-Ruby19_m17n
(私もまだ、半分も咀嚼できていませんが)

これによると、『スクリプト自体のエンコーディング』と『IOのエンコーディング』は別物として
扱うことができるということです。

ということで、下記のようなものでいかがでしょう

cmd.exe> ruby -e "Dir.glob(\"*.txt\").each { |fname| File.open(fname, \"r:EUC-JP:Windows-31J\"{ |fp| print fname if /ほげ/ =~ fp.readlines.join}}"

なお、コマンドラインオプション -Eを使ってdefault_external と default_internal を与える
こともできるとのことなので

cmd.exe> ruby -EEUC-JP:Windows-31J -e "Dir.glob(\"*.txt\").each { |fname| File.open(fname){ |fp| print fname if /ほげ/ =~ fp.readlines.join}}"

でも行けると思ったのですが、うまく動いてくれません。(環境依存かもしれませんが)

なおcmd.exe で動かしている関係でダブルクォーツを¥でエスケープしていますが、
11の環境はおそらくLinuxあたりだと思われますので、

sh> ruby -e 'Dir.glob("*.txt").each{ |fname| File.open(fname, "r:EUC-JP:UTF-8"){ |fp| print fname if /ほげ/ =~ fp.readlines.join}}'

あわせて、コマンドラインオプション -Eも試してみてください

あぁ、書き込んじゃってから思い至りました。

コンソール出力もIOですから、 -EEUC-JPを指定したらコンソールにeucで吐き出そうとして
うまくいかないワケですね。
やはり、ファイルオープン時にそのファイルのエンコーディングを指定してあげる必要が
あるのかな
あぁぁ、、、さらに訂正orz

M17Nは、多言語実装じゃなくて、多言語仕様、ですよね(^^;;

あと、
誤: cmd.exe> ruby -e "Dir.glob(\"*.txt\").each { |fname| File.open(fname, \"r:EUC-JP:Windows-31J\"{ |fp| print fname if /ほげ/ =~ fp.readlines.join}}"

正: cmd.exe> ruby -e "Dir.glob(\"*.txt\").each { |fname| File.open(fname, \"r:EUC-JP:Windows-31J\") { |fp| print fname if /ほげ/ =~ fp.readlines.join}}"

閉じ括弧が一箇所抜けてました。
# やっぱテキストエディタで書いてちゃんと推敲しないとダメですねぇ(反省)
『開かないリンクがあるんだけど?』というので覗いてみると、ディレクトリ名やファイル名に
Shift-JISがいっぱいで、7bit ASCIIのスペースや#が入っているステキファイル名も散見され。
(ちなみにサーバはWindows)

エレガントさのかけらもありませんが、これでなんとかなりました。
# 同一行に複数の<a>タグがあったら投げてたかも(^^;;

ruby -Ks -rkconv -ruri -i.bak -npe "if /<a +href=\"(.*?)\"/i then s = Kconv.toutf8($1); u = URI.encode(s); $_.sub!($1, u) end" index.htm
帰宅したので、少し整理してみました。

ruby -ruri -rkconv -npe "$_.sub!($1, URI.encode(Kconv.toutf8 $1)) if /<a +.*href=\"(.*?)\"/i" index.htm

ただ
(こういう行)ほげほげ(←こっちが置換されちゃう)<a href="ほげほげ">

こういう行があったらバグりますね(^^;;
まぁ、結果オーライだったワケですが(汗)

ps.
しかし、cmd.exe のダブルクォーツのエスケープは使いづらいなぁ。。。
>しかし、cmd.exe のダブルクォーツのエスケープは使いづらいなぁ。。。

確かに面倒です。
shだと、gawk '{printf "(%s)\n",$0}' と書くところを、CMDだと gawk -v a="(%s)\n" "{printf a,$0}" と書いたり。
3番で、「gawk の -v オプションのようなこと」と書いたのはそういう背景。


>if /<a +.*href=\"(.*?)\"/i
この場合はhrefのところをシングルクォートにすればエスケープ要らず。

久しぶりに作ってみたくなったので(汗)

ruby -e "def f(x)return[2] if x==2;a=f(x-1);a.each{|n|next if x%n!=0;return a};a<<x end;p f 100"
さすがに再帰で作るのは効率悪すぎですね。
8200弱でスタックがあふれました(苦笑) ← Windows x64環境です
ruby -e "a=[2];(3..100).each{|x|a<<x if a.each{|n|break if x%n==0}};p a"
再帰使わないで書き直してみました。
よく考えたら

ruby -e "a=[];(2..100).each{|x|a<<x if a.each{|n|break if x%n==0}};p a"

でいけますね。一文字減った(汗)
ブロックの中でbreak を使うとブロック全体の値としてnilを返す(*)っていうのが、
こんな風に便利に使えるんですねぇ

(*) break 式、と書くとブロックの値として任意の値を返せる
>> 21

ruby -e "a=[];(2..100).each{|x|a<<x if !a.find{|n|x%n==0}};p a"
>はなおかさん

ご教示ありがとうございます。
そうか、findか。。。思いつかなかったorz
で、もうちょっとひねってみました

ruby -e "a=[];(2..100).each{|x|a.find{|n|x%n==0}||a<<x};p a"

どうせなら再帰版のほうも:-)

ruby -e "def f(x)x==2?[2]:(a=f(x-1);a.find{|n|x%n==0}?a:a<<x)end;p f 100"

# ちょっとだけ関数プログラミング『風』になった気がする(^^;;
こんにちは、ALPHAです。

Rubyに限った話ではないのですが。。。
# 主にWindowsでの話題になるのですが。

a = お気に入りの(常用する)ワンライナーってお持ちですか?
if a then それって毎回手打ちしない方法をお持ちですか?

例えば、bashあたりならalias すればシアワセになれそうですが、
Windowsでcmd.exe だと使えないですし、ワンライナーのためにひとつずつ.batファイル
を作るんじゃ本末転倒ですし。。。

win-bash とか bash for Windows なんかも試してみたんですけど、
どうにも細かいところで苦労が多い(主にドライブレター周りや、基本ツール群で
日本語未対応のものがあったり)。
Cygwin みたいなOSにエミュレーションレイヤかぶせるタイプは他所の環境
(例えば職場等)でインストールできなくてストレス溜まりますし。。。

なにかよい解決策をお持ちの方いらしたらご教示いただけるとありがたく。


PS. win-bash はオフィシャルサイトに下記の説明があったんでいいかな、と思った
んですけど、ベースとなるbashのバージョンが古いんですよねぇ
Unlike other bash ports for windows (e.g. the cygwin bash), the win-bash needs no special environment or DLLs.
>26

alias程度の機能であれば、doskey のマクロ定義で出来ます。

ファイルに、
aaa=ruby -e "〜〜〜" $*
bbb=ruby -e "====”
などと書いておいて、doskey /macros:ファイル名
で、定義されます。詳しくは、doskey /? で。

コマンドプロンプト起動時に、毎回自動的にdoskeyコマンドを実行するようにしておけば便利です。
わたしは十数個定義してます。rubyのは無いですが。
> 27 otnさん

お返事遅くなってすみません。
doskey ってこんなコトできたんですね(汗)
MS-DOS時代の後期に登場したものだという記憶があって
調べてみたら確かにMS-DOS5から入っているようですが、
当時は便利な常駐フリーソフトがいっぱいあったので
目もくれてませんでした。。。
# DOSSHELLも、おんなじような目で見てたなぁ(汗汗)

今まで知らなかったってことは、あんまり必要性感じてなかったんですねぇ(恥)

ググると最初に出てくるページですが、doskey /? に載ってない情報もあるので
念のため
http://www.adminweb.jp/command/command/index2.html
GNU tac
ruby -ne "s||='';s=$_+s;END{$><<s}"
END キーワードを取りたいですねぇ・・・
こんにちは。ご無沙汰してます。

ちょっとアタマの体操に書いてみたんですが。。。。。
我ながらゴルフの才能がないですね。

ruby -e 'f="Fizz";b="Bazz";p (1..100).map{|v|v%15==0?(f+b):(v%3==0?f:(v%5==0?b:v))}'


バナー広告に画像のようなの見つけまして、『Ruby ならワンライナーでいけんじゃね?』とちょっと
頭の体操

$ ruby -e 'a=42;b=d=0;b=a.to_s(2).gsub("0","").length;s="";a.to_s.each_char{|c|s<< c.to_i.to_s(2)};d=s.gsub("0",").length;p (b==d)'
false

$ ruby -e 'a=52;b=d=0;b=a.to_s(2).gsub("0","").length;s="";a.to_s.each_char{|c|s<< c.to_i.to_s(2)};d=s.gsub("0","").length;p (b==d)'
true

出来たけどあまりスマートじゃないですね(^^;;
> 31
2桁の整数、つまり、10〜99の中に1の数が等しいものは幾つあるかという問題なので、aの値を10〜99にして調べて、個数を数えることになります。
もっとスマートにできるかもしれませんが、こんなのはどうでしょう。

puts (10..99).select{|e|e.to_s(2).gsub("0","").length == (e/10*16+e%10).to_s(2).gsub("0","").length}.size

出力は20でした。
>>[32]

あ、そうですね。設問は『2桁の整数、つまり、10〜99の中に1の数が等しいものは幾つあるか』
だからループ回す必要はありますね。

例の○×の部分だけみて書いてしまいました。
(設問よく読まずにバッテンもらうタイプだな^^;)

1の数を数える、ってのが、文字列にして、gsubで"0"を潰してlengthで数える、
しか思いつかなかったんですけど、ここがもっとスマートになれば、コードゴルフとしては
いい答案になりそうだとおもってます。。。。

ログインすると、残り2件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

Ruby 更新情報

Rubyのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング