2016-05-16 57 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)