SQL中伪列化数据的正则表达式解析
我在做一个项目,我们试图从联邦航空局发布的改道建议中解析信息。这些公告以自由文本形式发布,结构松散,目的是允许观众在一张纸上打印出来 最令人感兴趣的领域是咨询的最后部分,其中包含与给定改道相关的具体信息——始发地和目的地机场以及适用于它们之间任何航班的特定所需航线。下面是一个例子:SQL中伪列化数据的正则表达式解析,sql,regex,oracle,parsing,text,Sql,Regex,Oracle,Parsing,Text,我在做一个项目,我们试图从联邦航空局发布的改道建议中解析信息。这些公告以自由文本形式发布,结构松散,目的是允许观众在一张纸上打印出来 最令人感兴趣的领域是咨询的最后部分,其中包含与给定改道相关的具体信息——始发地和目的地机场以及适用于它们之间任何航班的特定所需航线。下面是一个例子: ORIG DEST ROUTE ---- --------------- ----------------------
ORIG DEST ROUTE
---- --------------- ---------------------------
FRG MCO TPA PIE SRQ WAVEY EMJAY J174 SWL CEBEE
FMY RSW APF WETRO DIW AR22 JORAY HILEY4
我想做的是能够将其解析为如下三个条目:
ORIG DEST ROUTE
---- --------------- ---------------------------
FRG MCO TPA PIE SRQ WAVEY EMJAY J174 SWL CEBEE
FMY RSW APF WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL
BINT LFV
YYT PSS TRI BABA TEN NINE FIVE
COL DMV
SAL PRT DUW PALO VR22 NOL3
ORIG DEST ROUTE
----- --------------------------- ------------------------------------------------------
FRG MCO TPA PIE SRQ FMY RSW APF WAVEY EMJAY J174 SWL CEBEE WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL BINT LFV
YYT PSS TRI BABA COL DMV TEN NINE FIVE
SAL PRT DUW PALO VR22 NOL3
原版:FRG
DEST:MCO TPA PIE SRQ FMY RSW APF
路线:WAVEY EMJAY J174 SWL CEBEE WETRO DIW AR22 JORAY Hiley 4
下面是我目前用来解析这部分咨询的三个代码段:
起源
regexp_substr(route_1,'^(([A-Z0-9]|\(|\)|\-)+\s)+')
目的地
regexp_substr(route_1,'(([A-Z0-9]|\(|\)|\-)+\s)+',1,2)
路由字符串
regexp_substr(route_1, '\s{2,}>?([A-Z0-9]|>|<|\s|:)+<?$')
regexp\u substr(路径1,'\s{2,}>?([A-Z0-9]|>概念证明)
输入文件是一个纯文本文件(没有制表符,只有空格)。在垂直方向上,它分为三列,固定宽度:20个字符,20个字符,剩余的任何字符(直到行尾)
前两行始终填充有标题和----
。这两行可以忽略。然后,文件的其余部分(向下读取页面)由ORIG列中最新的非空字符串“分组”
输入文件如下所示:
ORIG DEST ROUTE
---- --------------- ---------------------------
FRG MCO TPA PIE SRQ WAVEY EMJAY J174 SWL CEBEE
FMY RSW APF WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL
BINT LFV
YYT PSS TRI BABA TEN NINE FIVE
COL DMV
SAL PRT DUW PALO VR22 NOL3
ORIG DEST ROUTE
----- --------------------------- ------------------------------------------------------
FRG MCO TPA PIE SRQ FMY RSW APF WAVEY EMJAY J174 SWL CEBEE WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL BINT LFV
YYT PSS TRI BABA COL DMV TEN NINE FIVE
SAL PRT DUW PALO VR22 NOL3
请注意块之间的空行、一个块中的空DEST
(我处理这个问题,尽管可能是OP的问题,这是不可能的),以及在某些情况下DEST
和ROUTE
使用的行数不同
文件名是inp.txt
,它位于我向Oracle所知的一个目录中:将目录沙盒创建为'c:\app\sandbox'
(首先我必须将创建任何目录的权限授予
,同时以SYS
的身份登录)
输出如下所示:
ORIG DEST ROUTE
---- --------------- ---------------------------
FRG MCO TPA PIE SRQ WAVEY EMJAY J174 SWL CEBEE
FMY RSW APF WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL
BINT LFV
YYT PSS TRI BABA TEN NINE FIVE
COL DMV
SAL PRT DUW PALO VR22 NOL3
ORIG DEST ROUTE
----- --------------------------- ------------------------------------------------------
FRG MCO TPA PIE SRQ FMY RSW APF WAVEY EMJAY J174 SWL CEBEE WETRO DIW AR22 JORAY HILEY4
ABC SFD RRE BAC TRIO SBL CRT
POLDA FARM OLE BID ORDG BALL BINT LFV
YYT PSS TRI BABA COL DMV TEN NINE FIVE
SAL PRT DUW PALO VR22 NOL3
我分两步完成了这项工作。首先,我创建了一个助手表,INP
,它有四列(RN编号、ORIG varchar2(20)、DEST varchar2(20)、ROUTE varchar2(20))我通过一个过程从文本文件中导入。然后我进一步处理了这一点,并使用输出填充最终的表。这不太可能是最有效的方法(也许有很好的理由不这样做);我一般没有使用UTL_文件和将文本文件导入Oracle的经验。我这样做有两个原因:一是为了学习,二是为了证明是可以做到的
将文本文件导入助手表的过程:
Create or Replace PROCEDURE read_inp is
f UTL_FILE.FILE_TYPE;
s VARCHAR2(200);
rn number := 1;
BEGIN
f := UTL_FILE.FOPEN('SANDBOX','inp.txt','r', 200);
LOOP
BEGIN
UTL_FILE.GET_LINE(f,s);
INSERT INto inp (rn, orig, dest, route)
VALUES
(rn, trim(substr(s, 1, 20)), trim(substr(s, 21, 20)), trim(substr(s, 41)));
END;
rn := rn + 1;
END LOOP;
exception
when no_data_found then
utl_file.fclose(f);
END;
/
exec read_inp
/
以及进一步的处理(在创建重路由
表之后):
那么…这里的输入是什么呢?一个简单的ASCII文件,分为行和列,有两个标题行,然后行顺序有意义(原始列不是空的,用于标记新的数据库行)?您如何知道每行纯文本中DEST片段的结束位置和ROUTE片段的开始位置?列的左边缘是否位于固定位置?输入是否在多页上,每页上重复两行标题?您知道-您需要提供更多信息(除非您正在寻找以前使用过这种格式的人-祝您好运!)这是我第一次在这里发帖,所以在以后的帖子中我会记住你说的话。至于你的问题,正在读取的数据是Oracle数据库中的一列,其中包含咨询的全部文本。我唯一能描述“列”的方法在自由文本中,如果存在两个以上的空格(或行尾),则通过计算空格数,然后我的逻辑假设一个条目的末尾已经到达。我遇到的问题是,一些条目-目的地和路线-可以延续到多行。好的,这更清楚了。不过我看到了一个大问题:如果你真的只有一列,就没有“订单”的空间标记。你如何知道哪一行放在一起?表中的行就像篮子中的球-如果球没有标记,就无法知道球放在篮子中的顺序。如果你有办法对行进行排序,你可能会使用一些代码(和更一般的方法)我在回答中演示了。首先将文本行拆分为列(就像我直接从文本文件中所做的那样)然后进一步处理,如答案所示。@PhilSchrader-您的意思是整个通知存储为单个varchar2或CLOB值;因此每个通知在表中有一行?如果是这样,您可以在PL/SQL中逐行处理该CLOB并建立三个值。另外,看看您的示例和其他通知,这似乎是可能的让三个“字段”中的任何一个或全部拆分为多行。我不确定如果这三个字段都拆分了(即使是人类…)会发生什么情况,它们会添加一个空行或其他内容吗?我认为你的2-空格规则也不正确(看看今天的#069)。