我一直在考虑创建SRCDS(蒸汽游戏服务器(日志解析器,它将数据发送到数据库。在研究其他现有的解析器时,我偶然发现了 https://github.com/tomav/steam_hlds_log_parser,这完全 https://github.com/tomav/steam_hlds_log_parser/blob/master/lib/steam_hlds_log_parser/handler.rb
elsif @options[:display_disconnect] && data.gsub(/: "(.+)<'d+><.+><(.+)>" disconnected/).count > 0
player, player_team = data.match(/: "(.+)<'d+><.+><(.+)>" disconnected/i).captures
content = { :type => 'disconnect', :params => { :player => player, :player_team => get_short_team_name(player_team) } }
虽然 data.gsub(( 非常不言自明,我想几乎与preg_match相同,但变量(玩家,player_team(部分是神秘的。它是如何工作的,并且在 php 中是否可以在不做大量preg_matches来匹配字符串的不同部分的情况下实现类似的事情?上述代码的示例日志字符串为
# L 05/10/2000 - 12:34:56: "Player<73><STEAM_ID_LAN><TERRORIST>" disconnected
让我们一行一行:
elsif @options[:display_disconnect] && data.gsub(/: "(.+)<'d+><.+><(.+)>" disconnected/).count > 0
首先,它检查@options[:display_disconnect]
是否为真(即不是false
或nil
(,然后检查data
字符串是否与斜杠(/.../
(之间的正则表达式匹配。这是在 Ruby 中检查正则表达式匹配的一种非常糟糕的方法(我们有String#match
或=~
(,但它仍然有效。如果匹配,我们执行下一行:
player, player_team = data.match(/: "(.+)<'d+><.+><(.+)>" disconnected/i).captures
在=
的右侧,我们使用与以前相同的正则表达式调用String#match
(但这次使用i
标志 - 去图(。如果它匹配(我们已经在最后一行建立(,match
返回一个 MatchData 对象。此对象包含有关匹配的信息,例如,它从哪个位置开始,以及在 MatchData#captures
属性中捕获了字符串的哪些部分。
如果您不熟悉正则表达式,正则表达式中的括号表示"捕获组"。在我们的正则表达式中,我们有两个:一个捕获玩家名称(在您的示例中为"玩家"(,另一个捕获团队名称("恐怖分子"(。 captures
返回这两个字符串作为数组[ "Player", "TERRORIST" ]
。
在=
的左侧,我们有 player, player_team
.逗号表示"解构赋值"——它告诉 Ruby,如果 =
右侧的值表现得像数组,那么将第一个元素分配给player
,将第二个元素分配给player_team
,就像 PHP 中的list()
一样。换句话说:
player, player_team = [ "Player", "TERRORIST" ]
# ...is equivalent to:
captures = [ "Player", "TERRORIST" ]
player = captures[0] # => "Player"
player_team = captures[1] # => "TERRORIST"
最后:
content = { :type => 'disconnect',
:params => { :player => player,
:player_team => get_short_team_name(player_team) }
}
这将创建一个哈希(就像 PHP 中的关联数组一样(具有player
和player_team
值。它在 PHP 中的粗略等价物是:
$content = array( "type" => 'disconnect',
"params" => array( "player" => $player,
"player_team" => get_short_team_name($player_team) )
);
我希望对您有所帮助!
附言:就我个人而言,我会像这样编写Ruby代码:
DISCONNECT_EXPR = /: "(.+)<'d+><.+><(.+)>" disconnected/i
# ...
elsif @options[:display_disconnect] && data =~ DISCONNECT_EXPR
content = { :type => 'disconnect',
:params => { :player => $1,
:player_team => get_short_team_name($2) }
}
没有理由使用相同的正则表达式两次,当我们实际上没有进行任何替换时,也没有理由使用String#gsub
。