2016-05-16 59 views
1

破碎的报价冒号分隔值我有一个冒号分隔的文件cik.coleft.c,它看起来像这样:解析在bash

!J INC:0001438823: 
#1 A LIFESAFER HOLDINGS, INC.:0001509607: 
#1 ARIZONA DISCOUNT PROPERTIES LLC:0001457512: 
#1 PAINTBALL CORP:0001433777: 
$ LLC:0001427189: 
& S MEDIA GROUP LLC:0001447162: 
&TV COMMUNICATIONS INC.:0001479357: 
'MKTG, INC.':0000886475: 
11:11 CAPITAL CORP.:0001463262: 

这是一个两列csv其中分离逗号被替换用冒号。同时,单引号用逗号转义值,而不是冒号(分隔符)的值。

但是第一列包含冒号,这会破坏解析器。所以,当我尝试cik.coleft.c转换成正常csv ...

curl -o cik.coleft.c 'https://www.sec.gov/edgar/NYU/cik.coleft.c' 

in2csv --format 'csv' -d ':' -q "'" -e 'latin1' cik.coleft.c > cik.coleft.csv 

...我得到四个多列。

我试着用sed来读行,但没有成功。

如何将其转换为适当的两列表格?

+0

你可以选择一个不会与'11:11'之类的东西冲突的分隔符吗? –

+0

那么,唯一不正确的冒号是最后一行中的“11:11”? – Kaz

+0

您或创建该文件的人 - 通过替换分隔符来打破格式,而无需重新分析每个字段的引用要求。在“X”分隔值文件中天真地改变分隔符会破坏信息,导致这种模糊性。 (我知道这对你没有帮助,但这是对未来的教训,如果别人破坏了这个文件,你可以合法地抱怨。) – rici

回答

2

您可以使用awk,做一些字符串操作与subtrlength

awk 'BEGIN{OFS="|"}{col1=substr($0,1,length($0)-12);col2=substr($0,length($0)-10, 10);print col1,col2}' yourfile 

设置输出字段分隔符OFS管道|。它使用substr()length()划定了两列。第1列是从字符1开始到结束前12个字符处结束的。通过在记录结束前开始10个字符并抓取10个字符后找到第2列。

测试输出:

$ awk 'BEGIN{OFS="|"}{col1=substr($0,1,length($0)-12);col2=substr($0,length($0)-10, 10);print col1,col2}' test 
!J INC|0001438823 
#1 A LIFESAFER HOLDINGS, INC.|0001509607 
#1 ARIZONA DISCOUNT PROPERTIES LLC|0001457512 
#1 PAINTBALL CORP|0001433777 
$ LLC|0001427189 
& S MEDIA GROUP LLC|0001447162 
&TV COMMUNICATIONS INC.|0001479357 
'MKTG, INC.'|0000886475 
11:11 CAPITAL CORP.|0001463262 

这只能是因为你的第二个领域似乎永远是一个10位数字。如果文件的其他部分有所不同,那么您将不得不采取不同的路线。

2

可以向后

$ rev file | sed 's/:/~/3' | rev | column -ts: 

!J INC        0001438823 
#1 A LIFESAFER HOLDINGS, INC.  0001509607 
#1 ARIZONA DISCOUNT PROPERTIES LLC 0001457512 
#1 PAINTBALL CORP     0001433777 
$ LLC        0001427189 
& S MEDIA GROUP LLC     0001447162 
&TV COMMUNICATIONS INC.    0001479357 
'MKTG, INC.'      0000886475 
11~11 CAPITAL CORP.     0001463262 

知道有两列接近它,我们逆向而行,并与~更换:的第三个实例。

如果你有多余的需要更换,用gnu​​ sed使用g3而不是3后缀。

1

TXR可能的解决办法:

的策略是通过数据来匹配,但与线左右颠倒。为此,我们将使用@(next ...)的输入重定向到行的惰性:list,通过lazily mapping产生(get-lines)通过reverse函数的输出。以下是fixcolon.txr

@(next :list @[mapcar* reverse (get-lines)]) 
@(repeat) 
@ (assert) 
@ (cases) 
:@right:'@left' 
@ (or) 
:@right:@left 
@ (end) 
@ (do (put-line (reverse 
        (if (break-str left ":") 
        `:@right:'@left'` 
        `:@right:@left`)))) 
@(end) 

基本上只有两种情况:我们有一个单引号左或我们不知道。我们希望删除单引号(如果它们存在),并仅在字段包含冒号时重新设置它们。

以下额外的行已被添加到该数据:

11:11 CA:PI:TAL CORP.:0001463262: 

输出:

$ txr fixcolon.txr < data 
!J INC:0001438823: 
#1 A LIFESAFER HOLDINGS, INC.:0001509607: 
#1 ARIZONA DISCOUNT PROPERTIES LLC:0001457512: 
#1 PAINTBALL CORP:0001433777: 
$ LLC:0001427189: 
& S MEDIA GROUP LLC:0001447162: 
&TV COMMUNICATIONS INC.:0001479357: 
MKTG, INC.:0000886475: 
'11:11 CAPITAL CORP.':0001463262: 
'11:11 CA:PI:TAL CORP.':0001463262: 

多余的报价是围绕MKTG, INC.不见了。引用周围的11:11 ...字段。 (没有尝试处理嵌入的单引号,因为样本数据和问题文本没有指定或暗示任何要求)。

@(assert)确保模式匹配在与后面的情况不匹配的数据上发生异常。该指令有效地说:“我之后的一切都匹配,否则我就扔掉!”没有它,@(repeat)指令将跳过不匹配的数据。 (如果被告知不要跳过使用:gap 0,它会停在第一条不匹配的行,然后为了解决这个问题,我们需要断言我们在EOF)。

$ txr fixcolon.txr 
foo:bar: 
junk! 
[Ctrl-D][Enter] 
foo:bar: 
txr: unhandled exception of type assert: 
txr: (fixcolon.txr:3) assertion (at var:2) 
txr: during evaluation at fixcolon.txr:3 of form (assert)