Ruby字符串中的\'(反斜杠,单引号)

5
我正在使用Ruby 1.8.7,尝试生成一个包含\'字符的字符串,以便创建一个在MySQL中运行的脚本。结果应该像这样:
INSERT INTO table (name, description) values ('Joana d\'Arc', '')

但是我无法在 Ruby 字符串中只获取一个反斜杠。使用以下代码:

string = "INSERT INTO table (name, description) values ('Joana d\\'Arc', '')"

I got the following string:

INSERT INTO table (name, description) values ('Joana d\\'Arc', '')

同时使用以下技术:

string = "INSERT INTO table (name, description) values ('Joana d\'Arc', '')"

我收到了这个字符串:
INSERT INTO table (name, description) values ('Joana d'Arc', '')

2
也许这可以帮助你:http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Single%5Fquotes - Till Helge
2
如果您正在尝试在将文本插入SQL之前手动转义它,那么有更好的方法来完成这个任务。 - Romain
1
这两行代码 string = "INSERT INTO ..." 在我看来是一模一样的。我有什么遗漏吗? - Mike Samuel
1
不要被字符串的实际内容以及在控制台中如何显示(包括转义引号)所困惑,二者是有区别的。 - Gareth
此外,除非你喜欢修复和修补损坏的数据库,否则不要手动构建 SQL 字符串。 - Gareth
显示剩余3条评论
4个回答

6

我建议避免编写原始的SQL,在这个时代,即使是简单的数据库使用,我也会使用ORM。我强烈推荐使用Sequel宝石。从Sequel文档中借鉴一个示例

sequel sqlite://temp
Your database is stored in DB...

使用SQLite,在交互模式下启动Sequel ORM,并创建名为“temp”的SQLite数据库。

ruby-1.9.2-p290 :001 > require 'logger'
 => true 
ruby-1.9.2-p290 :002 > DB.loggers << Logger.new(STDOUT)
 => [#<Logger:0x0000010160bc40 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x0000010160bc18 @datetime_format=nil>, @formatter=nil, @logdev=#<Logger::LogDevice:0x0000010160bbc8 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<IO:<STDOUT>>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x0000010160bba0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x0000010160bb50>>>>] 

这样可以启用日志记录,以便我们在 Sequel 与数据库通信时可以看到其操作。

ruby-1.9.2-p290 :003 > items = DB[:items] # Create a dataset
 => #<Sequel::SQLite::Dataset: "SELECT * FROM `items`"> 
ruby-1.9.2-p290 :004 > DB.tables
I, [2011-11-25T10:17:13.056311 #10130]  INFO -- : (0.000501s) SELECT * FROM `sqlite_master` WHERE (type = 'table' AND NOT name = 'sqlite_sequence')
 => [] 

糟糕!我忘记创建表格了...

ruby-1.9.2-p290 :005 > DB.create_table :items do
ruby-1.9.2-p290 :006 >       primary_key :id
ruby-1.9.2-p290 :007?>     String :name
ruby-1.9.2-p290 :008?>     Float :price
ruby-1.9.2-p290 :009?>   end
I, [2011-11-25T10:17:20.985851 #10130]  INFO -- : (0.002372s) CREATE TABLE `items` (`id` integer PRIMARY KEY AUTOINCREMENT, `name` varchar(255), `price` double precision)
 => nil 

表格已创建。
ruby-1.9.2-p290 :010 > items = DB[:items] # Create a dataset
 => #<Sequel::SQLite::Dataset: "SELECT * FROM `items`"> 

这创建了一个数据集,它只是与表交互的一种方便方式。

而这就是回报:

ruby-1.9.2-p290 :011 > items.insert(:name => "Joan d'Arc")
I, [2011-11-25T10:17:45.186945 #10130]  INFO -- : (0.001981s) INSERT INTO `items` (`name`) VALUES ('Joan d''Arc')
 => 1

ORM自动为您转义字符。大大简化了您的工作。

ORM是DBM感知的,因此它们知道何时为特定数据库进行转义。您的代码没有改变。轻松切换从SQLite到MySQL,Postgres或非SQL数据库。


Sequel 能在旧版数据库上运行吗?我只能在该数据库上运行插入查询。 - klidebharrow
1
当然。使用它们非常好。我在工作中经常使用Sequel与传统的MySQL和MSSQL数据库进行通信。您可以在“数据集”模式下使用它,这是我的示例,或者您可以使用模型将其完全工作在对象模式下,允许表之间进行完全关系链接以进行查找和插入。它非常智能,生成简洁的SQL,并且不会用愚蠢的查询拖慢服务器。这是最好的gem之一。此外,支持它的Jeremy Evans也是这里的成员。您偶尔会从他那里得到问题的答复。 - the Tin Man
在我看来,自 readme 中最重要的例子是:DB['select * from items where name = ?', name].each...。也就是说,将 Sequel(或者说任何一个像样的 ORM)引入到你现有的代码中非常容易,而且现在没有理由不这样做了! :) - Mladen Jablanović
是的,能够快速整合原始SQL非常有用。这样做的缺点是会促进继续使用原始SQL,如果使用了特定于DBM的功能,则可能将代码与特定的DBM绑定在一起。使用提供的方法编程定义SQL可以消除这种耦合。 - the Tin Man

3

puts函数之所以有效是因为它显示了字符串中实际的内容。而裸露的控制台则是显示经过转义后的字符串。在控制台上尝试以下代码:

"Joana d\\'Arc".size

如果两个反斜杠都存在,您将得到12。 如果两个反斜杠都存在,则应该得到13。

Hauleth的答案应该有效。


是的,应该可以工作,实际上也确实如此,但只在控制台测试中有效。当查询在数据库中运行时,两个字符 \ 和 ' 都不会显示出来。 - klidebharrow
你可以尝试使用“Joana d'Arc”。 - seph
使用了四个反斜杠。谢谢Seph,你是我的英雄! - klidebharrow
1
不客气。另外,让我加入那些鼓励你尝试ORM的人的行列。它可能在这种情况下有所帮助,但它们还有许多其他好处。 - seph

1

使用%q{}表示法进行编写

string = %q[INSERT INTO table (name, description) values ('Joanna d\\'Arc', '')]

在控制台上运行良好,但在数据库上运行时,'不会显示出来。 - klidebharrow

0
你可以尝试这个:
string="INSERT INTO table (name, description) values ('Joana d"+"\\"+"'Arc','')"

我不知道你是否必须使用1.8.6版本,但如果可以的话,请升级到1.9.2版本。它更快、更稳定,还有更多的功能。


在控制台和应用程序上尝试了一下。在控制台中,结果是Joana d'Arc,有两个反斜杠和一个撇号。但是当涉及到数据库时,该名称被插入为Joana dArc,没有撇号。无论如何,谢谢! - klidebharrow
我不确定反斜杠的ASCII代码是什么,但你可以尝试将其附加到第一个字符串,然后再附加其余部分。虽然你尝试的所有方法都让我觉得你的解释器出了问题。双反斜杠应该始终转换为反斜杠。 - Linuxios

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接