08/10/29 11:47:31
CSV::Writer.generateを使ってCSV出力をしているようなんですが
出力されたCSVを見ると
AAA,BBB,CCC,DDD
と出力されており1データに改行が含まれている場合に正常に解析できなくなってます。
AAA,BBB,CCC,DD
D
本来ですと
"AAA","BBB","CCC","DD
D"
のようにデータが""で囲われてほしいのですが何か方法は無いでしょうか?
ソースは↓な感じですです。
def issues_to_csv(issues, project = nil)
ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
export = StringIO.new
CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
# csv header fields
headers = [ "#",
l(:my_data1),
l(:my_data2),
l(:my_data3),
]
csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
end
export.rewind
export
end
763:デフォルトの名無しさん
08/10/29 11:55:24
投稿者1人が半角スペースなコードをエディタに書く
↓
書き込み時に全角スペースに置換する
↓
参照者複数人が各々のコピペ時に全角スペースを置換する
↓
エディタに半角スペースなコードができる
まあ、プロトコル的に無駄ではあるな
投稿者が半角スペースを に置換してくれさえすれば参照者はコピペだけでおkなのに
2chブラウザによっては半角スペースを投稿時に に変換してくれるものもあるけどな
navi2ch使いあたりはこのへん全く意識しないはず
というか、全角スペース混じってると範囲実行のM-|ができなくてイラつく(w
いちいち
1 [1,2,3].each do |e|
2 puts e
3 end
と行番号つきで書かれるくらいムカつく
764:デフォルトの名無しさん
08/10/29 12:05:00
Jane Doe Styleで >>754 をコピーすると
半角スペースの箇所はクリップボードには &#160 (&#は半角)で保存されるぞ
アプリケーション( 2ch 含む)によって文字参照の扱いなんてまちまちなんだから
文字参照に変換してから貼れって主張にはあまり魅力を感じないんだよな
765:デフォルトの名無しさん
08/10/29 12:09:49
コピペ内容に関して意識してる2chブラウザはそう多くないよね
どうレンダリングするかとかはRFCに記述ないんだっけ?
766:デフォルトの名無しさん
08/10/29 13:14:44
なにやらえらい騒ぎになってしまったな。
全角半角が問題になるのはコピペする人間だけなのだが、実際それをする人間がどれ
ほどいるのか。
他の板ならともかく、いかに初心者スレとはいえここはム板なんだから、一括置換な
んぞ5秒でこなす
くらいの能力は期待できないものなのか。
学校のセンセじゃあるまいし、その程度は勘弁していただきたい。
まぁ、全角を使っているのは書き込みログが読みにくくなるから、というしょーもな
い理由なので、
こちらも置換すれば済む話ではあるし、専ブラで対処できるものなら導入を検討する
よ。
と、ここで新着見たら、そんな簡単な話しでもないのか。
確かに>>764は以前くらったことがあるな。
どうしたもんかね。
767:デフォルトの名無しさん
08/10/29 13:17:44
ノンブレイカブルスペースは \x20 とは別物。常識
768:デフォルトの名無しさん
08/10/29 16:32:30
おれも つかってたけど、>>764と同じことがあって、
結局全角スペースのほうが害がすくないと判断してる。
>>767
そうなんだよね。しかも が半角スペースにならない環境だと、
置換が全角スペースより面倒なんだよな。
まあ2chの仕様がクソということで。
769:デフォルトの名無しさん
08/10/29 16:33:42
>>762
CSVやめて、FasterCSVを使ってみたらどうでしょうか。
「ruby fastercsv」でぐぐってみてください。
770:デフォルトの名無しさん
08/10/29 17:08:50
>>769
実は先ほどソースはredmineのものなんです
ファイル名app\helpers\issues_helper.rb
なので簡単にFasterCSVに置き換えて大丈夫なものなのか判断しにくいんです。
変更は簡単ですかね?
771:デフォルトの名無しさん
08/10/29 22:43:51
>>762
CSV::Writer ならエスケープが必要なフィールドだけエスケープされるので、
以下のようになるはずだけど。
AAA,BBB,CCC,"DD
D"
DD\nDだけじゃなくてAAAとかもクォートして欲しいってこと?
772:デフォルトの名無しさん
08/10/30 13:30:47
>749-768
先頭の空白に関しては、まだRubyは良いほうでしょ
Pythonなんて先頭の空白が纏められたら話にならんかと
773:デフォルトの名無しさん
08/10/30 16:17:11
while文の中にif文入れられる?
774:デフォルトの名無しさん
08/10/30 16:22:19
a = [1, 2, 3]
while if n = a.shift
n
else
false
end
p n
end
# => 1
# => 2
# => 3
775:デフォルトの名無しさん
08/10/30 18:36:04
msg = "(1+2+3)*2/3" などのように数式の入った変数を
プログラムの構文として処理することは可能でしょうか?
val = 構文評価(msg)
のようなイメージで、
任意の数式をRubyで処理することを期待してるのですが
776:デフォルトの名無しさん
08/10/30 18:53:18
>>775
手っ取り早いのはeval。
でも数式に限らずなんでも実行できてしまうから
四則演算だけ処理したいならraccとそのサンプルのcalc.yあたりとか。
777:775
08/10/30 19:31:22
>>776
ありがとうございます。助かりました。
778:デフォルトの名無しさん
08/10/30 22:51:35
>>776
> 四則演算だけ処理したいならraccとそのサンプルのcalc.yあたりとか。
正規表現で入力を検査してokならevalに渡す方が楽でない?
779:デフォルトの名無しさん
08/10/30 22:58:30
そのへんは入力元がどのくらい信用できてどのくらい調教可能かによるな
780:デフォルトの名無しさん
08/10/30 23:07:18
信用できないから検査する。
何によるかというならどれくらい受理する式の文法を限定できるかだろう。
君、バカでしょ。
781:デフォルトの名無しさん
08/10/30 23:18:40
検査が必要かどうかという話だろ
自分で電卓代わりに使いたいだけなら入力検査は不要
こんなの完璧にやるか全くやらないかの2択なんだから信用度は重要
2//3 で エラー吐いて落ちるのは困るだろうし
1 2 + 3 で エラー吐いて落ちるのは困るだろうし
1/3*3 で 0 が返るのも困るだろうし
(1..2) で Range オブジェクトが返るのも困るだろう
782:デフォルトの名無しさん
08/10/31 00:02:44
>>781
君はバカさ加減の露出癖でもあるのかね。
> こんなの完璧にやるか全くやらないかの2択なんだから信用度は重要
不測の動作をさせないことが保証できればいいんだよ。
エラーはevalのすぐ外で捕捉すりゃいい話。
> (1..2) で Range オブジェクトが返るのも困るだろう
そうならないように検査するんだろうが。
783:デフォルトの名無しさん
08/10/31 00:03:55
じゃあraccでやれよ
784:デフォルトの名無しさん
08/10/31 00:06:22
は?
785:676
08/10/31 00:28:23
>>745
returnしたら、その後に行かないという基本的な事を知りませんでした。。。
説明していただいた内容が理解できていない部分があるので質問させて下さい。
「MATCHとINDEXまたはOFFSETとの組み合わせなら」とおっしゃっているのは、
それぞれ以下のもののことでしょうか?
URLリンク(www.ruby-lang.org)
URLリンク(www.ruby-lang.org)
URLリンク(www.ruby-lang.org)
それとも以下のようなexcelの関数のことでしょうか?
URLリンク(support.microsoft.com)
これすらも解からない状況です。申し訳ありませんがよろしくお願いいたします。
>>746-748
ループ版の早さは今の私には驚異的です!
1個のデータを処理するのにexcelで処理していたときは約5分
自分で作ったvlookupで約2分だったので、1秒かからなくなるんですね。
ただ、勉強不足でわからないことだらけです。
ループ版を自分で作るには時間がかかるので少し待って下さい。
完成したら添削をお願いします。
786:デフォルトの名無しさん
08/10/31 02:28:31
スレリンク(operate板:657番)
駄目元で書き込んだ。
賛同してくれる人はこのレスに同意のアンカーをつけてくれ。
787:デフォルトの名無しさん
08/10/31 04:54:23
>>785
コードの端々で妙な書き方してるから、他言語でヘンな癖でもつけて
きたのかと思ってたら、もしかしてプログラミング初心者だった?
Excel VBA使いを想定してたんだが、Excelもサッパリのようだし…
INDEXやOFFSET等、全部大文字で書いたのはExcelの関数。
これらについてはスレ違いなので他でよろしく。
まぁ、とりあえずは基本的な文法・制御構造をまず覚えてくれ。
最低限、分岐・ループ・メソッド呼び出しとそこからの脱出あたり。
勧めといてなんだけど例外は後回しでいいかな。
一度苦労した後の方が有り難みもよく分かるだろうし。
次に組み込みクラスについて調べてみる。
上で使ってるのは、数値(Numeric), 文字列(String), 範囲(Range)
あたりを見れば分かる程度の簡単な使い方してる。
重要なのは配列(Array)とEnumerableの2つ。
制御構造と並んで、こいつらがアルゴリズムを実装する要だ。
(今回は使わなかったが、Hashもいずれ知っておくべき)
クラスライブラリを全部覚えるのは大変だろうけど、どんなことが
できるかくらいはざっと目を通しておくといい。
そうしたらコードを読んでみる。
どれもかなり短いから、読み下すのはそう難しくないとおもう。
行数短縮のために三項演算子を濫用している点は申し訳ない。
788:デフォルトの名無しさん
08/10/31 04:58:30
コードを読んだだけでは内容を理解するのは難しいだろうから、
短い配列でどのような動きになるか、紙に書いてみるといい。
再帰をループに変更するにはアルゴリズムを十分に理解して
いなければならないが、是非がんばって挑戦してほしい。
ケチな高速化など後回しと書いた理由も実感して貰えたと思うが、
もし興味を持ったなら、アルゴリズムも勉強してみてはどうか。
ほんのちょっとの仕組みの違いで速度が千倍とかざらにあるよ。
計算量の考え方だけでも知っておくことをお勧めする。
789:デフォルトの名無しさん
08/10/31 07:54:59
VB系はreturnに直接相当する命令がないからな。
戻り値と、プロシージャを抜ける構文が別になってるから。
で、そのまま直訳してreturnとbreakに分けた、と。そんな感じだろう。
790:デフォルトの名無しさん
08/10/31 10:38:32
ひとこといわせてくれ。
>>787-788、おつ。こんごもがんがれ。
791:デフォルトの名無しさん
08/10/31 17:14:09
あるクラスAが別のクラスBのサブクラスかどうかを判定するメソッドってありませんでしたっけ?
今は
A.ancestors.include?(B)
とやってるんですけど、かっこわるいですよね。
792:デフォルトの名無しさん
08/10/31 17:21:41
どうして?それでよいのでは?
793:デフォルトの名無しさん
08/10/31 17:45:25
class B;end
class A < B; end
class C; end
p A < B
p A > B
p A < C
794:デフォルトの名無しさん
08/10/31 17:51:24
>>793
>> File < IO
=> true
>> Dir < IO
=> nil
なにこれーーー
>> Fixnum < Integer
=> true
>> Array < Enumerable
=> true
module もOKだ
ちょうさんくすです
795:デフォルトの名無しさん
08/10/31 18:44:55
まさかModule/Class同士の比較ができるとは・・・知らなかった
796:デフォルトの名無しさん
08/10/31 21:10:08
>>795
伊達に継承の記号が "<" なわけじゃない。
……かどうかは知らないが。
797:デフォルトの名無しさん
08/11/01 06:26:05
VIPから来ますた
798:デフォルトの名無しさん
08/11/01 06:26:45
VIPから来ますた
799:デフォルトの名無しさん
08/11/01 06:28:45
∧_∧
( ´・ω・) みなさん、VIPからさし入れのお茶が入りましたよ・・・・。
( つ旦O
と_)_) 旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦
800:デフォルトの名無しさん
08/11/01 06:44:02
VIPから来ますた
801:728
08/11/01 08:48:50
検索機能がついに完成しました。
一応私の夢見た掲示板をついに作り終えました。
とはいえまだ課題がいくつか残ってます。
それを今後つぶしていきます。
802:デフォルトの名無しさん
08/11/01 11:00:45
以下のスクリプトで,30行目で,
usr/lib/ruby/1.8/net/http.rb:451:in `initialize': wrong number of arguments (2 for 1) (ArgumentError)
のエラーが出てしまいます。
比較のためにAとBを作ったのですが、29行目ではエラーが出ません。
Net::HTTPを承継したクラスを作って,コンストラクタの部分を
オーバーライドしようとしています。
エラーの原因は何でしょうか
1 #!/usr/bin/ruby
4 require 'net/http'
5 require 'uri'
7 class A
8 def initialize(arg)
9 puts "A initialized", arg
10 end
11 end
13 class B < A
14 def initialize
15 puts "B initialized"
16 end
17 end
19 class C < Net::HTTP
20 Net::HTTP.version_1_2
21 def initialize(url)
22 uri = URI.parse(url)
23 puts "C initialized"
24 super(uri.host, uri.port)
25 end
26 end
28 url = 'URLリンク(www.yahoo.co.jp)'
29 p b = B.new
30 p c = C.new(url)
803:デフォルトの名無しさん
08/11/01 12:21:28
URIはHTTP専用ってわけじゃないので、ちゃんとプロトコルから書く。
あとNet::HTTPはわりと残念な設計で、サブクラスでinitializeをオーバーライドしても呼ばれない。
委譲したほうがいいかも
804:デフォルトの名無しさん
08/11/01 19:52:20
>>802
これで我慢すれ
class C < Net::HTTP
def initialize(*args)
args[0].kind_of?(URI) ? super(args[0].host,args[0].port) : super
end
end
805:デフォルトの名無しさん
08/11/02 08:33:41
そこでhttpclientですね
806:デフォルトの名無しさん
08/11/02 12:26:17
802 じゃないけど、なんであのエラーが出るのか理屈がわからない…。>>802 の initialize にダミー引数を渡すと呼ばれるよね。
require 'net/http'
require 'uri'
class C < Net::HTTP
Net::HTTP.version_1_2
def initialize(url, dummy=nil)
uri = URI.parse(url)
puts "C initialized"
super(uri.host, uri.port)
end
end
url = 'URLリンク(www.yahoo.co.jp)'
p c = C.new(url)
Net::HTTP を眺めて同じ挙動を再現しようと思ったけど、できないYO!
class A;end
class << A; alias newobj new; end
class A
def A.new(foo, bar=nil)
a = A.P(foo, bar).newobj(foo, bar)
end
def initialize(foo, bar=nil)
puts "A init."; @foo = foo; @bar = bar
end
def A.P(foo, bar=nil);self;end
end
class B < A
def initialize(foo)#, bar=nil)
puts "B init."; super(1, 2)
end
end
p b = B.new(3)
807:デフォルトの名無しさん
08/11/02 17:50:27
>>806
× a = A.P(foo, bar).newobj(foo, bar) # in A.new
○ a = self.P(foo, bar).newobj(foo, bar)
808:806
08/11/03 00:21:05
おおお!!thx>>807
なんで、A付けちゃったんだろ?
これを色々いじって、マニュアル見ながらよく考えてみる。
も一回ありがとう!>>807
809:デフォルトの名無しさん
08/11/03 17:14:38
ディレクトリの中にあるすべてのファイル名を変えるプログラムを作ろうとしたのですが
5分で挫折しました(笑)
File.open("D:\\Data") {|f|
puts f.to_str()
}
とりあえずこうやってファイル名を出力しようとしたのですが、
コマンドプロンプトではすべてUNICODEのファイル名で表示されてしまい
わけわかめです。
$SCODE = SJISとかやってもダメでした
810:デフォルトの名無しさん
08/11/03 17:28:30
それファイル名じゃなくdataというファイルの中身を読んでいるように思えるが
`dir d:\\data /b`.each { |f| f.chop!
puts f
}
811:デフォルトの名無しさん
08/11/03 17:39:07
その場合メソッドパラメタの名前は line とかのほうがいいぞ
812:デフォルトの名無しさん
08/11/03 17:42:01
メソッドパラメタ → ブロックパラメタ
813:デフォルトの名無しさん
08/11/03 17:58:21
>>809
そういうときは、致命的な動作になるまでは Dirl.glob を使う
ディレクトリ区切り文字は \ ではなく / なので注意
irb> Dir.glob('c:/*')
["c:/AUTOEXEC.BAT", "c:/boot.ini", "c:/bootfont.bin", "c:/CONFIG.SYS", "c:/Documents and Settings",
"c:/Program Files", "c:/RECYCLER", "c:/ruby", "c:/System Volume Information", "c:/WINNT"]
irb> Dir.glob('c:/*/')
["c:/Documents and Settings/", "c:/Program Files/", "c:/RECYCLER/", "c:/ruby/",
"c:/System Volume Information/", "c:/WINNT/"]
irb> Dir.glob('*.txt')
["001.txt", "002.txt", "003.txt"]
irb> Dir.glob('*.txt').each{|e| FileUtils.mv(e, "#{File.basename(e,'.*')}.bak") }
irb> Dir.glob('*')
["001.bak", "002.bak", "003.bak"]
814:デフォルトの名無しさん
08/11/03 18:15:13
>>813
今のrubyは\も扱ってくれるよ
と思ってたが、Dir.globは\区切りに対応してないのね……
815:デフォルトの名無しさん
08/11/03 20:31:28
下のディレクトリの中も再帰的にやるんじゃなかったら
Dir.entries(ディレクトリのパス).reject{|d| File.directory? }
とか。
816:デフォルトの名無しさん
08/11/04 00:14:51
rubyでファイルの種類の判断ってできますか?
拡張子で判断するのではなくファイルの中身で、Excelファイルかどうかの判断が
したいんです。
よろしくおねがいします。
817:デフォルトの名無しさん
08/11/04 01:34:00
できますよ
818:デフォルトの名無しさん
08/11/04 03:33:29
>>816
がんばってマジックナンバー嫁
819:デフォルトの名無しさん
08/11/04 08:17:09
>>816
unix系ならFileMagicだけどwindowsはよう知らん
820:デフォルトの名無しさん
08/11/04 19:22:11
>>815
Windowsですが
再帰でディレクトリリストが欲しい時もcmdのdirですましちゃう
サブディレクトリ一覧
dir /s /ad /b \ほげほげ\ | ruby -ne "puts $_”
ほげほげ下のサブディレクトリ内の.rbファイル一覧
dir /s /a-d /b \ほげほげ\*.rb | ruby -ne "puts $_"
とか
rubyだけでやるならglobで/**/使って
Dir.glob('/ほげほげ/**/*/'){|e| puts e}
とか
Dir.glob('/ほげほげ/**/*.rb'){|e| puts e}
と、いろいろ試してたら列挙される数が違ったんで、あれっ?と思ったら
globの方は標準ではドットファイルが除外されるのを忘れてた
使用してるのがWindowsオンリーなので、普段ドットファイルなんて意識しないし
Dir.glob('/ほげほげ/**/*.rb',File::FNM_DOTMATCH){|e| puts e}
821:デフォルトの名無しさん
08/11/05 21:56:06
>>816
エクセル持って無いけど
たぶんファイルの先頭見たら判るんじゃね?とググって見ると
エクセルもワードも BIFFってフォーマット(OLE?)でどっちもファイルの先頭は同じだったorz
さらにぶらぶらと調べてたら、parseexcelっていうライブラリを見つけたので
適当にインターネットからxlsファイルを落としてきて
require 'parseexcel'
workbook = Spreadsheet::ParseExcel.parse('エクセルのサンプルファイル.xls')
で読み込めたけど、えらく遅かったので parseexcel がパース直前にやってることを直に書いてみた
require 'parseexcel'
begin
ole= OLE::Storage.new('エクセルのサンプルファイル.xls')
biff = ole.search_pps([OLE.asc2ucs('Book'),OLE.asc2ucs('Workbook')],true)
if biff.first
puts "エクセルファイル"
else
raise 'NotExcelfile'
end
rescue
puts "エクセルファイルじゃない"
end
エクセルファイルを漏れなく判定できるのかはわかりませんが…
822:デフォルトの名無しさん
08/11/06 11:05:21
require 'foobar'
としたあとで、'foobar.rb' の絶対パスを調べる方法ってありますか。
823:デフォルトの名無しさん
08/11/06 15:13:55
File.expand_path($LOAD_PATH.map{|d| File.join(d, 'foobar.rb') }.find{|path| File.exist?(path) })
824:デフォルトの名無しさん
08/11/06 15:19:42
>>823
それは読み込んだファイルであることを保証しない
825:デフォルトの名無しさん
08/11/06 15:27:19
読み込んだファイルそのものを指定することは1.8ではできないと思った
同名のファイルをファイルパスから探すことはできるけれど
>>823で問題になる場合というのはなくはないとは思うが非常にレアなような気もする
826:デフォルトの名無しさん
08/11/06 15:32:16
foobar.rb で File.expand_path(__FILE__) を返すようなメソッドなりなんなりを用意しておくほうが確実なのかな
>>823の要件に合うとは思えないけど
827:デフォルトの名無しさん
08/11/06 15:35:43
>>826
require を拡張したほうが妥当と思う
が、どうすればいいのやら
gem の require はどうやってるんだっけ
828:デフォルトの名無しさん
08/11/06 15:43:39
foobar.rb で File.expand_path(__FILE__) を返すようなメソッドなりなんなりを
requireしたあとからくっつければ医院で内科医?
829:デフォルトの名無しさん
08/11/06 16:20:11
>>828はのび太
830:デフォルトの名無しさん
08/11/06 17:55:23
>>823-828
どうもありがとうございます。
ないということなので、以下の方法で済ませることにしました。
lib = "foobar.rb"
dir = $:.find{|path| File.exist?(File.join(path, lib)) }
filepath = dir ? File.join(dir, lib) : nil
ありがとうございました。
831:デフォルトの名無しさん
08/11/06 21:45:52
拡張子省いてrequireしたとき、.soだったのか.rbだったのかまで知りたくなったら、$LOADED_FEATURESとも突き合わせて比較する必要も出てくる。
832:デフォルトの名無しさん
08/11/07 00:21:42
突然ごめん。
p array
した時の["hoge", "fuga", "boo"]みたいな書式って
変更できたりしない?
あと一歩でcsvなので便利に使えそうなんだが。
pのことをググって調べるのは非常にホネが折れる…
833:デフォルトの名無しさん
08/11/07 00:28:03
inspect
834:デフォルトの名無しさん
08/11/07 01:07:55
>>832
URLリンク(www.ruby-lang.org)
なんでもぐぐって調べようとするから骨が折れてるんだろうw
835:デフォルトの名無しさん
08/11/07 02:12:54
>>832
joinの方が楽
836:デフォルトの名無しさん
08/11/07 03:23:57
>>832
>>835
その名も「csv」というライブラリが標準で付いてることを忘れないでやってくれ。
837:デフォルトの名無しさん
08/11/07 09:49:56
>>832
一文字目と最後の文字消せばいいだけじゃね?
838:デフォルトの名無しさん
08/11/07 12:18:53
なんでもかんでもググるって馬鹿がすることだよね。
賢い人なら知りたいことが見付かりそうな文書はどこにあるのかをまずは考える。
839:デフォルトの名無しさん
08/11/07 20:15:46
ロックシステムについて相談があるんですが
i=0
begin
File.open('lockfile',File::WRONLY|File::CREAT|File::EXCL,0666) do |lfile|
File.open('hoge','r') do |file|
# hogeを使ったいろいろな処理
end
end
File.unlink('lockfile')
rescue SystemCallError
if(i>10) then raise
i+=1
if(File.stat('lockfile').mtime<Time.new+10) then
File.unlink('lockfile') #残骸のロックファイル削除
else
sleep(0.1)
end
retry
end
どうもi386-mswin32だとEXCLオープンしても例外を投げなくてうまくいかない
ようです。他のプラットフォームだとどうなんでしょう?
840:デフォルトの名無しさん
08/11/07 21:16:58
File#flock() を使う方法しかしらない。
File.open("foobar.txt", "wb") do |f|
f.flock(File::LOCK_EX) # 排他ロック
f.unlock();
end
841:デフォルトの名無しさん
08/11/07 21:22:21
なんか既視感がある
組み込みで妥当に動作してるロック機構を再発明しようとするな、というのがアドバイスだったはず
842:デフォルトの名無しさん
08/11/07 21:24:54
>>840
まずそのサーバーでflockが使えないから無理
>>841
組み込みで現に存在してるのが使えないから問題。
確認したいこと
1.とりあえず方法があっているか。
2.Windowsだとまともに動かないようだが他のプラットフォームだとどうか。
843:デフォルトの名無しさん
08/11/07 21:35:38
>>839
1.8.6-FreeBSDだけど File::CREAT|File::EXCL で Errno::EEXIST が出る
ただし>>839のソースをそのまま実行すると例外が rescue でとらえられて
例外処理でロックファイル削除されてからリトライするから、例外が発生してないように見える
あとrescueの下の二行間違ってるよ
844:デフォルトの名無しさん
08/11/07 21:40:52
>>839
$ ./ruby.exe -v -e 'open("hoge", File::WRONLY|File::CREAT|File::EXCL,0666)'
ruby 1.8.7 (2008-11-04 revision 20103) [i386-mswin32]
-e:1:in `initialize': File exists - hoge (Errno::EEXIST)
投げるが。
> if(File.stat('lockfile').mtime<Time.new+10) then
未来の時刻と比較してるようだがこれはいいのか?
845:デフォルトの名無しさん
08/11/07 21:43:49
>>843
確かにおかしいところがあるかもしれないです。
rescue
if(i>10) then
raise
end
i=i+1
if(File.stat('lockfile').mtime<Time.new+10) then
File.unlink('lockfile') #残骸のロックファイル削除
else
sleep(0.1)
end
retry
end
一応rescue節の書き換えはしてみました。これで大丈夫でしょうか。
あと、例外処理でロックファイルが削除されるのはたぶん正しいです。
というのもそのファイルの最終更新時間が10秒以上前なら削除するように
できてますから。
846:デフォルトの名無しさん
08/11/07 21:45:56
>>844
あ、やばい。そこがおかしい。
どう考えてもおかしい。
if(File.stat('lockfile').mtime+10<Time.new) then
こう直すべきだ
847:デフォルトの名無しさん
08/11/07 21:55:09
>>844
どこでおかしかったか分からないが治った。thx
848:デフォルトの名無しさん
08/11/07 21:57:23
>>842
> 組み込みで現に存在してるのが使えないから問題
849:デフォルトの名無しさん
08/11/07 22:10:05
>>842
> 1.とりあえず方法があっているか。
あってない。突っ込み所満載。
・SystemCallError なんて上がらないんだが。
rescue => e
puts e.class
とでもして、何が上がってるのか確認しろ。
・if文が閉じてねーぞ。
> if(i>10) then raise
1行で書きたきゃ「if(i>10) then raise; end」か「raise if (i>10)」だ。
つか、endの対応が合ってなくてさくっとsyntax errorなんだが……。
・mtimeが「現在+10秒」より過去、って何の冗談だ。
・あるプロセスがunlinkした直後に別のプロセスがstatしたら死ぬんだが。
・あるプロセスがstatしてunlinkするまでの間に別のプロセスがstatしてunlinkしてopenしたら不味いんだが。
> 2.Windowsだとまともに動かないようだが他のプラットフォームだとどうか。
とりあえず適当に修正したら、2プロセス程度の簡単なテストならちゃんと動いた。(@mswin32)
850:デフォルトの名無しさん
08/11/07 22:19:35
>>849
1.Errno::XXX系統のクラスは全部SystemCallErrorのサブクラスなので
きちんと受け止められる
2.if文問題は修正済み
3.時間問題も修正済み
4.いまだにレースコンディションが解消してない件は最悪またSystemCallErrorで
受け止めてやればいい
修正したソース(rescue節のみ記載)
rescue
if(i>10) then
raise
end
i=i+1
begin
if(File.stat('lockfile').mtime+10<Time.new) then
File.unlink('lockfile') #残骸のロックファイル削除
else
sleep(0.1)
end
rescue SystemCallError
#rescueするけど何もしない
end
retry
end
851:デフォルトの名無しさん
08/11/07 22:24:21
それでもやっぱり最後のレースコンディションは解消してないのだが、
これ以上この方法にこだわる限り改善の余地はなさそう。
852:デフォルトの名無しさん
08/11/07 22:42:44
>>842
>まずそのサーバーでflockが使えないから無理
File#flock() が使えない環境ってどんなの?
どこでも使えるもんだと思ってた。
853:デフォルトの名無しさん
08/11/07 23:03:27
>>850
更新時刻から10秒待つのに、リトライは0.1秒×10回でいいのか、というのはおいといて、ゴミ掃除を別々のプロセスで確実にやるのは無理だと俺は判断してる。
ゴミ掃除専用のプロセスを1個だけ別に動かしとけ。メインの処理に10秒以上かかる可能性がないと言えるなら、それで大丈夫だろ。
854:デフォルトの名無しさん
08/11/07 23:31:32
どうせ専用のプロセスを立ち上げるなら,
druby使ってmutexを共有するという強引な方法を思いついた
855:デフォルトの名無しさん
08/11/08 00:22:16
普通にO_EXLOCKでシステムのアドバイザリロック機構に頼ればいいんじゃないのか?
下がnfsだったりするとアレだが。
856:デフォルトの名無しさん
08/11/08 05:41:35
>>853-854
レンタルサーバーでCGIを動かすために使うというのが大前提なので。
プロセスの常駐とかまず無理。
10秒待つのではなく確実を期すために10秒以上前のロックファイルを
削除するといっている。待つ時間は1秒。
857:デフォルトの名無しさん
08/11/08 05:43:07
flockメソッド(関数)は、言語によって同じ名前でも実装が違ったり
一部のファイルシステムやレンタルサーバ上では使えなかったりしてあまり信用できない
かといって自分でロック機構を実装すれば、レースコンディションの危険がある
なんかこの辺をさくっと解決してくれるpure rubyなライブラリないかな
858:デフォルトの名無しさん
08/11/08 11:34:57
>>857
>flockメソッド(関数)は、言語によって同じ名前でも実装が違ったり
Rubyの話してるんだから他の言語は関係ないだろ。
>一部のファイルシステムやレンタルサーバ上では使えなかったりしてあまり信用できない
だからどんなファイルシステムやレンタルサーバ上で使えないの?
具体名をだしてくれ。
どういう場合にflockが使えないのかを、ドキュメントに書いてもらおうぜ。
859:デフォルトの名無しさん
08/11/08 12:23:44
>>858
NFS上でのロックは不可能。
これはflockシステムコールの実装から来る制約。
fcntlを使えばNFSでロックすることは可能になるがIO.ioctl関数という
可搬性が低いメソッドを用いなければならず(まずWindowsなら実装されていないと
門前払い)かなり面倒。おまけにたいていNFS上でのロックはセキュリティホールに
なるので使えないのが普通。
860:デフォルトの名無しさん
08/11/08 12:49:31
>>858
レンタルサーバだと、flockが明示的に禁止されているサーバがある。パンドラとか
ただ、現在flockを使えないサーバがどのくらいあるかは分からない
無視できるほど少数かも
861:デフォルトの名無しさん
08/11/08 22:07:38
正規表現の書き方なのですが、、、、
>Sector:</td><td class="yfnc_tabledata1"><a href="URLリンク(biz.yahoo.com)">Services<
こんな文字列があって、前後にも改行以外の文字が色々とくっついているのですが、
Sector:の後のServicesをマッチさせて文字としてとってこようとすると、どう書けば良いでしょうか?
862:デフォルトの名無しさん
08/11/08 22:17:18
正規表現は書き方を覚えないと駄目
なぜなら、ほんの少し変えようと思っただけで別物になるから
コピペでやろうとすると異常に遠回りになる
正規表現自体は他の言語の正規表現とけっこう互換性があるから適当なサイトで勉強すれ
863:デフォルトの名無しさん
08/11/09 00:42:26
>>862
ありがとうございます。
マッチしたい文字列が9種類しかないのが分かったので、こうやりました。
if line =~ /.*Sector:<.*(Basic Materials|Conglomerates|Consumer Goods|Financial|Healthcare|Industrial Goods|Services|Technology|Utilities)/
p $1
end
864:デフォルトの名無しさん
08/11/09 11:46:37
wxRubyについて勉強してるんですが、何かいいサイトはありますか?
一応自力で見つけたサイト
URLリンク(www.gesource.jp)
URLリンク(wx.k5-n.com)
最小限のことは自分でやってます。require周りは自分でなんとかしてます。
865:デフォルトの名無しさん
08/11/09 11:59:40
具体的には…
1.とりあえずwxWindowをインストールした
2.wxRubyをgems経由でインストールした
3.簡単なテストアプリケーションが動くようになった
以上のことがすでに完了してます。
866:デフォルトの名無しさん
08/11/09 12:00:00
文字列変換メソッドを多数持たせたモジュールがあります。呼び出し
ごとに正規表現オブジェクトが作成されるのを防ぎたいのですが、
単に/abcde/ の代わりにRegexp.new("abcde")とすればOKですか?
それともグローバル変数みたいなものに格納しないとキャッシュと
しての効果は出ない?
867:デフォルトの名無しさん
08/11/09 12:12:20
式展開を含まないならどうでもいい
868:デフォルトの名無しさん
08/11/09 12:18:17
>>866
irb> class RegData
def reg1; /abc/; end
def reg2; /ABC/; end
def reg3; /123/; end
end
irb> RegData.new.reg1
/abc/
irb> RegData.new.reg1.object_id
537973880
irb> RegData.new.reg1.object_id
537973880
irb> RegData.new.reg1.object_id
537973880
ということで、静的な正規表現は、クラス定義が読み込まれた時点で使いまわしモードに入る
@re_scan = /xxxx.+?(yyy)zzz+/i
のようにクラス変数に正規表現を保管するというようなよくあるテクニックは、
正規表現が静的である場合に限り、コスト上は実は無意味、あるいは参照コストのぶん損だったりする
>>867の言うように、式展開を含むような「毎回違う可能性のある」正規表現はこの限りではない
869:デフォルトの名無しさん
08/11/09 12:20:32
>>866
/abc/ なら毎回生成されることはない。
/ab#{var}cd/ や Regexp.new("abcd") なら毎回作成される。
あとは
CACHE_REGEXP = {}
def cache_regexp(str)
CACHE_REGEXP[str] ||= Regexp.new(str)
end
とか。
870:デフォルトの名無しさん
08/11/09 12:42:43
>>864
公式のチュートリアル。
あとWxWidgetsのサイト全般と公式のAPIドキュメント。
wxに限ったことではなく、既存ライブラリのRubyバインディングは
元ネタのサイト漁るのが一番いいと思う。
871:デフォルトの名無しさん
08/11/09 12:57:40
>>870
読んでみたんですが、すでに???状態です。
英語ワカンネじゃなくてそもそも読む気力がないのが大問題だったりするわけですがorz
今度気力が回復したらやってみます
872:デフォルトの名無しさん
08/11/09 13:09:11
わかんなくてもコードコピペしてたら何となく動くし
それでもダメならWxWidgets関連のサイト参考にって>>870の2-4行目で
873:デフォルトの名無しさん
08/11/09 13:15:24
>>872
ええ。一応その段階はある程度OKです。
あとはゆっくり亀のように進んでいけばいいんです。
解決しました。ありがとうございます。
874:デフォルトの名無しさん
08/11/09 13:23:24
>>864
harukaze wxPython で検索
あと、解説サイトじゃないけど
wxRuby開発者が出してるwxsugarオススメ
875:デフォルトの名無しさん
08/11/09 13:49:02
>>874
たぶん言ってるサイトはこれだと思うんだけど、
URLリンク(www.harukaze.net)
なんかドメイン飛んでるよ
Pythonのが参考になるっつーことは理解できたけど。
876:866
08/11/09 15:29:30
>>867-869
ありがとう、よく分かりました。
877:デフォルトの名無しさん
08/11/10 23:22:19
>>859
>NFS上でのロックは不可能。
ほう、そうなのか。知らなかった。さんくす。
>fcntlを使えばNFSでロックすることは可能になるがIO.ioctl関数という
>可搬性が低いメソッドを用いなければならず(まずWindowsなら実装されていないと
>門前払い)かなり面倒。
Windows上でNFSを使うことはないだろうから、ioctlはUNIX限定でいいんじゃね?
>おまけにたいていNFS上でのロックはセキュリティホールに
>なるので使えないのが普通。
これよくわかんないんだけど、理由は?参考になるURLプリーズ。
>>860
>レンタルサーバだと、flockが明示的に禁止されているサーバがある。パンドラとか
これも理由がわからん。レンタルサーバでNFS使ってるわけじゃないだろうし。なんで?
878:デフォルトの名無しさん
08/11/10 23:31:11
>>877
URLリンク(menu.pandora.nu)
パンドラ側の説明みつけた
879:デフォルトの名無しさん
08/11/11 00:06:10
超絶初心者な質問で申し訳ないんですけど、RubyScript2Exeでexeファイル作りたいんですけど上手くいきません。
使い方は、RubyScript2Exe.rbとexeにしたいファイルを同じフォルダに入れて、
コマンドプロンプトで、「ruby [RubyScript2Exeのパス] [exeにしたいファイル]」
で合っていますか?
880:デフォルトの名無しさん
08/11/11 07:32:00
>>878
サンクス。あきらかにNFS使ってるね。
そんなサーバがあることに驚いたけど。
881:デフォルトの名無しさん
08/11/11 07:50:04
つまりflock前提として、最適なロック方法は
「まずIO.ioctlでロックを試みる、エラーが出ればrescueしてflockする」ということか!
・・・面倒だ
やっぱり、完全に可搬性のあるファイルシステムロック用のライブラリが欲しいな
882:デフォルトの名無しさん
08/11/11 08:19:04
「完全に」とか簡単に言っちゃう人って頭悪そう。
883:デフォルトの名無しさん
08/11/11 08:36:33
不完全or不安定なライブラリがほしいって言うのもなんだと思うが
884:デフォルトの名無しさん
08/11/11 08:49:34
欲しい欲しい、して欲しい。
885:デフォルトの名無しさん
08/11/11 09:14:19
RAAやRubyForgeをざっと探してみたけど、ファイルロック用のライブラリらしきものが見当たらない
実はみんな、あまり必要としていないのか?
MLでこんな古い話は見つけたが、ソースコードはもう公開されてないっぽい
(時間ないから詳しく探してないけど)
URLリンク(blade.nagaokaut.ac.jp)
886:デフォルトの名無しさん
08/11/11 09:50:16
本来、ファイルロックみたいにべったり環境依存なものに、完全な可搬性を求める発想が普通は余りないんだよね。
とはいうものの「環境依存だから諦めろ」ってのも古い考えで、こういう操作こそ処理系で環境差異を吸収しろ、っていう意見も、確かに一つの見識だと思う。
というわけで、完全な可搬性を持ったファイルロックの実装をコントリビュートしてくれ。
887:デフォルトの名無しさん
08/11/11 09:54:31
あんまり気にしたこと無かったけど、makeするあたりで
良きに計らってくれるとよさそうな感じだね
888:デフォルトの名無しさん
08/11/11 15:07:35
flockが使えるかどうかがファイルシステムに依存する以上、
コンパイル時に判定するのは無意味じゃないか?
889:デフォルトの名無しさん
08/11/11 17:32:32
>>886
SQLが使えるなら簡単な表を作って、そこに1つだけレコードを追加して、
あとはSELECT FOR UPDATEかSELECT LOCK IN SHARE MODEで終了。
幸いSQL用のライブラリは普通に配布されてる。
SQLが使えない場合はやり方を工夫するしかないわけなんだが。
とりあえずパンドラさんのPerlライブラリを解析するしかなさそうだけど。
>>881
むしろ順番は逆のほうがいい。ioctl関数はどちらかといえば汎用関数。
ioctlが使えないのはほぼ例外なくWindowsで作られてるサーバー。
890:デフォルトの名無しさん
08/11/11 17:34:51
RuBBSになんかあったな、ロック用のモジュール。
これの可搬性はどうなんだろう。
URLリンク(www.google.com)
891:デフォルトの名無しさん
08/11/11 17:53:13
>>890
この関数の流れは…
1.ロックファイルを固有ファイルに名前を変えようとする。成功したら3へ
2.失敗したらタイムアウトより古いロックファイルがあればロックを取得しようとする。
成功したら3へ
3.1秒待って1へ戻る。ただしtry回試して失敗したら打ち切り
4.ロックを取得できていなければLockError例外を発生させる
5.ブロックをともなって呼び出されていた場合そのブロックを実行する。
そしてロックを解放する
ロックの解除は普通に元のファイル名に変更するだけ。
汎用性はかなり高いと思われる。レースコンディションを検討しても
まずないだろうと考えられる。ファイルのリネームができないサーバーは
まずないだろうからその面でも問題はない。
892:デフォルトの名無しさん
08/11/11 18:01:12
ただし、このプログラムを使う場合、GPL2が適用されるので
それを使ったソースの配布もGPL2を用いなければならず、
そこが唯一の問題だったりする。逆に言えば、GPL2で
配布する予定のプログラムならぜんぜん問題はないといってよい。
893:デフォルトの名無しさん
08/11/11 19:05:10
>>892
自分で書き直せばいいんじゃね?
894:デフォルトの名無しさん
08/11/11 22:36:42
アトミックな処理(シンボリックリンクの作成とか)を利用したロック方法は
それなりにノウハウが枯れきっている話題だし、自分で実装しちゃえばいい。
895:デフォルトの名無しさん
08/11/12 07:21:48
試しにファイルシステムロック用のライブラリを書いてみた(不完全)
mkdir方式で共有ロック・排他ロックの区別あり
URLリンク(eload.run.buttobi.net)
ロック検出→ロックディレクトリ作成の間に
明らかなレースコンディションがあるんだけど、解決の方法が思いつかない・・・
何かいい解決策はないだろうか
896:デフォルトの名無しさん
08/11/12 12:34:09
すでに存在するディレクトリを指定したときにエラー返らないんだっけ?
897:デフォルトの名無しさん
08/11/12 13:20:39
Perlだけど解説は参考になるかな
URLリンク(www.din.or.jp)
898:デフォルトの名無しさん
08/11/12 21:36:28
>>896
Errno::EEXIST
899:デフォルトの名無しさん
08/11/13 08:41:51
改良版。レースコンディションは無くなった……と思う
その代わり1回のロックで2つのディレクトリを作るため、効率はやや悪い
URLリンク(eload.run.buttobi.net)
>>896
共有ロックだと、複数のロックを同時にかけられるから
「まずmkdirしてみて、失敗するならロックされている」という検出方法が使えなかった
900:デフォルトの名無しさん
08/11/13 16:44:54
ボロボロじゃん。
教科書に載るようなちゃんと知られたアルゴリズムを調べて書いた方がいいと思うよ。