问题:我需要解析纳斯达克的.tip文件。官方名称:GENIUM CONSOLIDATED FEED
文件是一个csv文件,带有分号和换行符,用于不同结构的新条目,因此没有常量标题。但它有一个相应的xsd模式文件,它应该描述内容和结构,但我看不出从文件到结构结果的明确方法。尝试过列表设置,其中messageType成为列表中的名称
x <- scan("cran_tasks/NOMX_Comm_Close2.tip", what="", sep="\n")
y <- strsplit(x, ';')
names(y) <- sapply(y, `[[`, 1)
y <- sapply(y, `[`, -1, simplify = FALSE)
y <- sapply(y, as.list)
文件的结构如下:
messageType;key1Value;key2Value;...;..;/n
messageType;key1Value;key2Value;.....;/n
BDSr;i2;NAmGITS;
BDx;i106;Si18;s2;SYmNC;NAmNASDAQ OMX Commodities;CNyNO;MIcNORX;
BDm;i672;Si018171;s2;Ex106;NAmFuel Oil;SYmNCFO;TOTa+0200;LDa20141011;
BDIs;i10142;SiNP;s2;ISsNP;NAmNord Pool ASA;
m;i122745;t191500.001;Dt20170509;ISOcY;ISOtY;
m;i122745;t192808.721;Dt20170509;ISOcN;ISOtY;SEp275.45;
Oi;i122745;t054425.600;OPi2840;
我有一个工作的sql代码集来解析文件,但它已经证明是针对特定情况,即使是结构上的微小变化也是如此,例如不同keyValue对的顺序。所以我正在寻找利用信息结构的方法,以便能够制作一个强大且可维护的解决方案,最好在R中。我尝试过一些正则表达式匹配,但我最终还是有很多特定的上下文代码,所以我希望使用包含Key信息的表或数据框的一些结构可以实现可持续的解决方案。
任何提示或建议都非常受欢迎。
指向XML/XSD文件和html sheet指定密钥以及.tip file
的链接提示消息格式TIP协议是标记文本协议。一个 提示消息是由一系列标记和值对分隔开的 分号。标签是零个或多个大写字符后跟一个 小写字符。标签后面紧跟着值。 标签的示例是“FLd”,“STa”。消息中的第一个标记是 始终是消息类型。消息类型标记没有值。一个例子 消息类型标记的“BDSh”。 IP消息使用UTF-8编码 除非另有说明。 TIP消息的最大长度为 用常量MAX_MESSAGE_LENGTH(2048字节)表示。任何 最大字段长度排除任何转义字符'\'。没有空值 将被发送;例外是消息类型标签和布尔标签( 标签本身的存在对应于“真实”值。为一个 十进制字段(即浮点数据类型)的长度为X,Y 其中X是字段整数部分的最大位数 (分隔符左侧)。 Y是小数位数(右边的) 分隔器)。传播标签的顺序不固定,即 客户可能不会对标签的顺序做出任何假设。唯一的 消息的固定组件是消息类型,它始终是 首先放在消息数据中。请注意新消息和字段 可以在协议的未来版本中添加。确保前进 兼容性,客户端应忽略无法识别的消息类型和 字段标签。
答案 0 :(得分:1)
下面的data.table
解决方案解析给定的.tip文件,并返回带有标记和值对的data.table。因此,这可能是进一步提取相关数据的良好起点。
library(data.table)
# read downloaded file from local disk
tip_wide <- fread(
"NOMX_Comm_Close2.tip"
, sep = "\n"
, header = FALSE
)
# split tip messages into tag and value pairs
# thereby rehaping from wide to long format
# and adding a row number
tip_long <- tip_wide[, unlist(strsplit(V1, ";")),
by = .(rn = seq_len(nrow(tip_wide)))]
# get message type tag as the first entry of each message
msg_type <- tip_long[, .(msg.type = first(V1)), by = rn]
# make message type a separate column for each tag-value-pair using join
# remove unnecessary rows
tip_result <- msg_type[long, on = "rn"][msg.type != V1]
# split tag and value pairs
tip_result[, c("tag", "value") :=
data.table(stringr::str_split_fixed(V1, "(?<=^[A-Z]{0,9}[a-z])", 2))]
tip_result
# rn msg.type V1 tag value
# 1: 1 BDSr i2 i 2
# 2: 1 BDSr NAmGITS NAm GITS
# 3: 2 BDx i106 i 106
# 4: 2 BDx Si18 Si 18
# 5: 2 BDx s2 s 2
# ---
#905132: 95622 BDCl s2 s 2
#905133: 95622 BDCl i2368992 i 2368992
#905134: 95622 BDCl Il2368596 Il 2368596
#905135: 95622 BDCl Op1 Op 1
#905136: 95622 BDCl Ra1 Ra 1
请注意,value
列的类型为字符。
正则表达式 "(?<=^[A-Z]{0,9}[a-z])"
使用 look-behind断言(请参阅?"stringi-search-regex"
)来定义拆分模式。请注意,此处使用{0,9}
代替*
,因为后视模式不得无限制(无*或+运算符。)