2012-09-22 24 views
10

Tek tek SQL deyimleri almak ve bunları ray denetleyicisinden çalıştırmak için bir dosyayı ayrıştırmam gerekiyor.Sınırlayıcıyı ayırmadan ayırma dizesi

Aşağıdaki kod var:

@sql_file = "#{RAILS_ROOT}/lib/evidence_interface_import.sql" 
@sql_stmts_array = File.read(@sql_file).split(";") 

@sql_stmts_array.each_with_index do |sql_stmt,s_index| 
    ActiveRecord::Base.connection.execute(sql_stmt) 
end 

bölünmüş kaldırır ";" SQL'lerin sonundan. ";" Yi kaldırmamak için bir yol var mı ve hala ";" ile ayrılır.

cevap

3

ile regex (Örn select * from stuff where name = ";";.):

@sql_stmts_array = File.read(@sql_file).lines(separator=';') 
+1

Sözdizimi satırlar için yanlıştır (Ayırıcı ='; ')' - bu işe yarayacaktır ama kötü yazılmış. Bunun yerine satırlar (';') 'olmalıdır. Ancak, 'File.readlines (@sql_file, ';')' yi kullanın çünkü daha kısadır ve aynı şeyi gerçekleştirir. Tonlama ve string manipülasyonunu içeren birçok vaka için –

1

split ile benzer sonuçları veren uygun bir regex ile scan kullanmayı deneyebilirsiniz, ancak normal ifadesi olmayan bir yolla yapıştırmak isterseniz, dizideki her hücreye yalnızca bir yarı kalın çizgi ekleyebilirsiniz:

@sql_stmts_array = File.read(@sql_file).split(";").each do |s| 
    s << ";" 
end 
+2

Bu son girmesinden sonra bir noktalı virgül koyarak bir yan etkiye sahiptir. – willglynn

+1

Bu istenen değil mi? Her girişten sonra bir '' 'olmamalı mı? – siame

13

Evet, scan o:

'a; b; c;'.scan(/[^;]*;/) 
#=> ["a;", " b;", " c;"] 

Sen sonra map(&:strip) orsalayarak tarafından aşırı boşluk kurtulmak olabilir, ama muhtemelen burada ihtiyaç değil.

Bunun çok ilkel olduğunu ve içinde bir noktalı virgül olan SQL'de bir dize değişmezi gibi bir şeyin bunu kıracağını unutmayın.

+1

Benzer bir seçenek şöyle olurdu: 'a; b; c; '. scan (/.*?;/) ' – Sajjad

3

kullanın Bu çalışan bir olan ileriye dönük

split(/(?<=;)/) 
6

ilk etapta noktalı virgül dahil etmek gerekmez ActiveRecord::Base.connection.execute kullanarak.

Ayrıca sınırlayıcı çıkarmadan bölme için başka bir yol, aşağıdaki örnekte gösterildiği gibi grupları kullanmaktır:

"a;b;c".split(/;/) # => ["a", "b", "c"] 

"a;b;c".split(/(;)/) # => ["a", ";", "b", ";", "c"] 
+1

- bu harika bir çözümdür. –

+0

Bunu kabul edilen cevap olarak işaretlerim. 'scan', her bir öğenin ardında sadece aralarında değil, sınırlayıcıya ihtiyaç duyuyor gibi görünüyor. –