在bash

时间:2016-05-16 18:20:44

标签: bash parsing csv sed

我有一个冒号分隔的文件cik.coleft.c,如下所示:

!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读取这些行,但没有成功。

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

3 个答案:

答案 0 :(得分: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开始到12个字符结束,找到第1列。通过在记录结束前开始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位数字。如果文件的其他部分有所不同,那么你必须采用不同的路线。

答案 1 :(得分:2)

你可以从后面接近它

{{ app.request.locale }}

知道有两列,我们将该行反转,并用$ 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后缀。

答案 2 :(得分:1)

TXR中的可能解决方案:

策略是匹配数据,但是从左到右反转。为此,我们使用@(next ...)将输入重定向到lazily mapping行的(get-lines)行,@(assert)通过:list函数生成。以下是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.字段引入的。 (不会尝试处理嵌入式单引号,因为示例数据和问题文本未指定或暗示任何要求)。

{{3}}确保模式匹配爆发,数据异常与后续案例不匹配。该指令有效地说明了我之后的一切,或者我扔了!&#34;没有它,11:11 ...指令将跳过不匹配的数据。 (如果被告知不要跳过使用@(repeat),它将在第一个不匹配的行停止。然后要抓住这个问题,我们需要断言我们在EOF)。

:gap 0