将 ruby 日志解析器转换为 PHP


Converting ruby log parser to PHP

我一直在考虑创建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]是否为真(即不是falsenil(,然后检查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 中的关联数组一样(具有playerplayer_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