首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Python编码解析CS:GO语言文件

用Python编码解析CS:GO语言文件
EN

Stack Overflow用户
提问于 2016-03-12 07:33:52
回答 1查看 1.3K关注 0票数 3

这个主题与Parsing a CS:GO script file in Python主题有关,但还有另一个问题。我正在编写CS的一个内容:GO,现在我正在尝试制作一个python工具,将/script/文件夹中的所有数据导入Python字典。

解析数据后的下一步是从/resources解析语言资源文件,并在字典和语言之间建立关系。

有一个用于Eng本地化的原始文件:english.txt

文件格式与以前的任务类似,但我面临另一个问题。所有的语言文件都是用UTF-16-LE编码,我无法理解用Python处理编码文件和字符串的方法(我主要是使用Java),我尝试过基于open(fileName, encoding='utf-16-le').read()制定一些解决方案,但是我不知道如何在Python解析中处理这样的编码字符串。

pyparsing.ParseException:预期引号字符串,以“结尾”开头(字符0),(行:1,col:1)

另一个问题是带有\"-like表达式的行,例如:

代码语言:javascript
复制
"musickit_midnightriders_01_desc"       "\"HAPPY HOLIDAYS, ****ERS!\"\n    -Midnight Riders"

如果我想保持这些符号的原样,如何解析这些符号?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-12 20:09:47

这个输入文件有一些新的缺陷,不在原始CS:GO示例中:

  1. 嵌入的\"在某些值字符串中转义引号
  2. 一些引用的值字符串跨越多行。
  3. 有些值以尾随环境条件(如[$WIN32][$OSX])结尾。
  4. 在文件中嵌入注释,标记为'//‘

前两个问题是通过修改value_qs的定义来解决的。由于值现在比键功能更全面,所以我决定为它们使用单独的QuotedString定义:

代码语言:javascript
复制
key_qs = QuotedString('"').setName("key_qs")
value_qs = QuotedString('"', escChar='\\', multiline=True).setName("value_qs")

第三个问题需要更多的重构。这些限定条件的使用类似于C中的#IFDEF宏--只有当环境与条件匹配时,它们才启用/禁用定义。其中一些条件甚至是布尔表达式:

  • [!$PS3]
  • [$WIN32||$X360||$OSX]
  • [!$X360&&!$PS3]

这可能导致定义文件中的重复键,如以下几行:

代码语言:javascript
复制
"Menu_Dlg_Leaderboards_Lost_Connection"     "You must be connected to Xbox LIVE to view Leaderboards. Please check your connection and try again." [$X360]
"Menu_Dlg_Leaderboards_Lost_Connection"     "You must be connected to PlayStation®Network and Steam to view Leaderboards. Please check your connection and try again." [$PS3]
"Menu_Dlg_Leaderboards_Lost_Connection"     "You must be connected to Steam to view Leaderboards. Please check your connection and try again."

其中包含键"Menu_Dlg_Leaderboards_Lost_Connection“的3个定义,这取决于设置了哪些环境值。

为了在解析文件时不丢失这些值,我选择在解析时通过附加条件来修改键。此代码实现更改:

代码语言:javascript
复制
LBRACK,RBRACK = map(Suppress, "[]")
qualExpr = Word(alphanums+'$!&|')
qualExprCondition = LBRACK + qualExpr + RBRACK

key_value = Group(key_qs + value + Optional(qualExprCondition("qual")))
def addQualifierToKey(tokens):
    tt = tokens[0]
    if 'qual' in tt:
        tt[0] += '/' + tt.pop(-1)
key_value.setParseAction(addQualifierToKey)

因此,在上面的示例中,您将得到3个键:

  • 菜单_Dlg_引导板_丢失_连接/$X 360
  • 菜单_Dlg_引导板_丢失_连接/$PS3
  • Menu_Dlg_Leaderboards_Lost_Connection

最后,注释的处理可能是最简单的。Pyparsing支持跳过注释,就像空格一样。您只需要为注释定义表达式,顶层解析器就会忽略它。为了支持这一特性,在common解析中预定义了几种常见的注释形式。在这种情况下,解决方案只是将最终的解析器定义更改为:

代码语言:javascript
复制
parser.ignore(dblSlashComment)

最后,在QuotedString的实现中存在一个小错误,其中标准空格字符串文本(如\t\n )不被处理,只是被视为不必要的转义't‘或'n’。所以现在,当这一行被解析时:

代码语言:javascript
复制
"SFUI_SteamOverlay_Text"  "This feature requires Steam Community In-Game to be enabled.\n\nYou might need to restart the game after you enable this feature in Steam:\nSteam -> File -> Settings -> In-Game: Enable Steam Community In-Game\n" [$WIN32]

对于您刚刚得到的值字符串:

代码语言:javascript
复制
This feature requires Steam Community In-Game to be enabled.nnYou 
might need to restart the game after you enable this feature in 
Steam:nSteam -> File -> Settings -> In-Game: Enable Steam Community 
In-Gamen

而不是:

代码语言:javascript
复制
This feature requires Steam Community In-Game to be enabled.

You might need to restart the game after you enable this feature in Steam:
Steam -> File -> Settings -> In-Game: Enable Steam Community In-Game

我将不得不在下一版本的pyparsing解析中修复此行为。

下面是最后的解析器代码:

代码语言:javascript
复制
from pyparsing import (Suppress, QuotedString, Forward, Group, Dict, 
    ZeroOrMore, Word, alphanums, Optional, dblSlashComment)

LBRACE,RBRACE = map(Suppress, "{}")

key_qs = QuotedString('"').setName("key_qs")
value_qs = QuotedString('"', escChar='\\', multiline=True).setName("value_qs")

# use this code to convert integer values to ints at parse time
def convert_integers(tokens):
    if tokens[0].isdigit():
        tokens[0] = int(tokens[0])
value_qs.setParseAction(convert_integers)

LBRACK,RBRACK = map(Suppress, "[]")
qualExpr = Word(alphanums+'$!&|')
qualExprCondition = LBRACK + qualExpr + RBRACK

value = Forward()
key_value = Group(key_qs + value + Optional(qualExprCondition("qual")))
def addQualifierToKey(tokens):
    tt = tokens[0]
    if 'qual' in tt:
        tt[0] += '/' + tt.pop(-1)
key_value.setParseAction(addQualifierToKey)

struct = (LBRACE + Dict(ZeroOrMore(key_value)) + RBRACE).setName("struct")
value <<= (value_qs | struct)
parser = Dict(key_value)
parser.ignore(dblSlashComment)

sample = open('cs_go_sample2.txt').read()
config = parser.parseString(sample)


print (config.keys())
for k in config.lang.keys():
    print ('- ' + k)

#~ config.lang.pprint()
print (config.lang.Tokens.StickerKit_comm01_burn_them_all)
print (config.lang.Tokens['SFUI_SteamOverlay_Text/$WIN32'])
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35955019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档