.match的多字节字符问题?

时间:2015-01-09 21:30:21

标签: ruby regex multibyte

以下代码是我开始测试在我正在使用的“Texas Hold Em”风格游戏中使用的代码。

我的问题是,为什么在运行以下代码时,涉及“♥”的put会在其中返回“\ u”。我确信这是多字节字符导致第二次放置的问题,我用字符串数组中的d替换了♦它返回了我期待的内容。见下文:

我的代码:

#! /usr/bin/env ruby
# encoding: utf-8

table_cards = ["|2♥|", "|8♥|", "|6d|", "|6♣|", "|Q♠|"]

# Array of cards

player_1_face_1 = "8"
player_1_suit_1 = "♦"

# Player 1's face and suit of first card he has

player_1_face_2 = "6"
player_1_suit_2 = "♥"

# Player 1's face and suit of second card he has

test_str_1 = /(\D8\D{2})/.match(table_cards.to_s)

# EX: Searching for match between face values on (player 1's |8♦|) and the |8♥| on the table

test_str_2 = /(\D6\D{2})/.match(table_cards.to_s)

# EX: Searching for match between face values on (player 1's |6♥|) and the |6d| on the table

puts "#{test_str_1}"
puts "#{test_str_2}"

进入屏幕:

|8\u

|6d|

- 我的目标是获得第一批投注:| 8♥|

我不是在寻找一个解决方案(可能甚至没有一个),但更多的是“尽可能简单”解释造成这个问题的原因和原因。提前感谢您提供有关此处发生的事情以及如何解决目标的任何信息。

1 个答案:

答案 0 :(得分:1)

您看到的“\ u”是Unicode字符串指示符。

例如,Unicode字符'HEAVY BLACK HEART'(U + 2764)可以打印为“\ u2764”。

友好的Unicode字符列表网站是http://unicode-table.com/en/sets/

您是否能够在shell中启动交互式Ruby并打印出这样的心脏?

irb
irb> puts "\u2764"
❤

当我在Ruby中运行代码时,我得到了你期望的答案:

test_str_1 = /(\D8\D{2})/.match(table_cards.to_s)
=> #<MatchData "|8♥|" 1:"|8♥|">

如果您尝试使用更适合您卡片的正则表达式,会发生什么?

 test_str_1 = /(\|8[♥♦♣♠]\|)/.match(table_cards.to_s)

在您的示例输出中,您没有看到所需的Unicode心形符号。相反,您的输出是打印“\ u”这是Unicode启动器,但然后不打印其余的期望字符串“2764”。

  • 请参阅Tin Man的评论,其中介绍了控制台的编码。如果他是正确的,那么我希望更具体的正则表达式会成功,但仍会输出错误的输出。

  • 请参阅David Knipe的评论说它看起来像被截断,因为正则表达式只匹配4个字符。如果他是正确的,那么我希望更具体的正则表达式会成功并打印正确的输出。

(这个答案的其余部分对于Unix来说是典型的;如果你在Windows上,请忽略其余部分......)

要显示您的系统语言设置,请在您的shell中尝试:

echo $LC_ALL
echo $LC_CTYPE

如果它们不是“UTF-8”或类似的东西,请在你的shell中试试:

export LC_ALL=en_US.UTF-8
export LC_CTYPE=en_US.UTF-8

然后重新运行您的代码 - 确保使用相同的shell。

如果这样做,并且你想让这个永久化,那么一种方法是在这里添加:

# /etc/environment
LC_ALL=en_US.UTF-8
LC_CTYPE=en_US.UTF-8

然后从.bashrc或.zshrc或您使用的任何shell启动文件中获取该文件。