【问题标题】:Plain text table to csv linux纯文本表到csv linux
【发布时间】:2019-07-10 16:44:51
【问题描述】:

我有一些明文表格,需要以 csv 格式输出 如果我执行 tr 并替换字符,当我有 2 行时,我的字段会出现一些问题。

cat file.txt | tr -s '|' ' ' | tr -s '_' ' '

原表:

 ____________________________________________________________________________
|      Name                 |   AB    | DATA     | SOME  | IF     | DATE    |
|___________________________|_________|__________|_______|________|__(UTC)__|
|   Marra Carolina Odoriz   |         |          |       |        |2019-07- |
|           Dolman           |36737202 |098787267 |  45   |   -    |09T10:35:|
|____________________________|_________|__________|_______|________|_50.289Z_|
|                            |         |          |       |        |2019-07- |
|             -              |53959997 |098543650 |  30   |   -    |09T12:02:|
|____________________________|_________|__________|_______|________|_36.746Z_|
|                            |         |          |       |        |2019-07- |
|      Vic Velazquez         |33577915 |096638025 |   -   |  6000  |09T12:40:|
|____________________________|_________|__________|_______|________|_17.754Z_|
| Gabriela Letacia Cararallo |         |          |       |        |2019-07- |
|         Vacchetzi          |43132876 |091322398 |  30   |   -    |09T12:40:|
|____________________________|_________|__________|_______|________|_40.887Z_|

我需要 csv 的输出 对于这个简单的表格示例:

NAME;AB;DATA;SOME;IF;DATE (UTC)
Marra Carolina Odoriz Dolman;36737202;098787267;45;-;2019-07-09T10:35:50.289Z
-;53959997;098543650;30;-;2019-07-09T12:02:36.746Z
Vic Velazquez;33577915;096638025;-;6000;2019-07-09T12:40:17.754Z
Gabriela Letacia Cararallo Vacchetzi;43132876;091322398;30;-;2019-0709T12:40:40.887Z

如果我有没有“table ascii”设计的原始多行输入文件,可以将此部分解决方案应用到案例中吗? 我已经申请了:

while(<>)
{

    @vals = split /\ /; # split fields into the val array (now I take the blank space)
    $size = @vals;
    for( $i = 0 ; $i < $size ; $i++ )
    {
        #clean up the values: remove underscores and extra spaces
        #remove semicolons
        $vals[$i] =~ s/_/ /g;
        $vals[$i] =~ s/;/ /g;
        $vals[$i] =~ s/^ *//;
        $vals[$i] =~ s/ *$//;

        # append the value to the data record for this field
        $data[$i] .= $vals[$i];

        # special handling for first field: use spaces when joining
        $data[$i] .= " " if ($i==0);
    }
   if(/\R/)  # Taking four underscores to indicate the end of the record 
             # now taking the return of carriage of new line how end of the record
    {
        # clean up the first record; trim spaces
        $data[0] =~ s/^ *//;
        $data[0] =~ s/ *$//;
        $data[3] =~ s/\..*//;

        # join the records with semicolons
        $line = join (";", @data);

        # collapse multiple spaces
        $line =~ s/ +/ /g;

        # print this line and start over
        print "$line\n" unless ($line eq '');
        @data = ();
    }
}

有了这个解决方案,结果是:

姓名;完整;;;;;;;;;AB;;;;;;;数据;;;某些;;日期;(UTC) 马拉;卡罗来纳州;奥多里兹;;;;;36737202;098787267;45;-;2019-07-09T10:35:50.289Z

多尔曼 ;;;

【问题讨论】:

  • 对于 *nix 基于行的文本工具来说,这看起来像是一场噩梦。也许perl 模块可以解决它,但您需要一位顾问。我会花时间试图说服原始表的提供者让您访问他们的数据源,或者提供您需要的输出。祝你好运。

标签: linux csv text


【解决方案1】:

多行处理在 shell 中很困难,但在 perl 中却很容易。

blocktab2csv.pl:

while(<>)
{
    chomp; # remove newline
    s/^\|//; # remove pipe at the start of the line

    @vals = split /\|/; # split fields into the val array
    $size = @vals;
    for( $i = 0 ; $i < $size ; $i++ )
    {
        #clean up the values: remove underscores and extra spaces
        $vals[$i] =~ s/_//g;
        $vals[$i] =~ s/^ *//;
        $vals[$i] =~ s/ *$//;

        # append the value to the data record for this field
        $data[$i] .= $vals[$i];

        # special handling for first field: use spaces when joining
        $data[$i] .= " " if ($i==0);
    }
    if(/____/)  # Taking four underscores to indicate the end of the record
    {
        # clean up the first record; trim spaces
        $data[0] =~ s/^ *//;
        $data[0] =~ s/ *$//;

        # join the records with semicolons
        $line = join (";", @data);

        # collapse multiple spaces
        $line =~ s/ +/ /g;

        # print this line and start over
        print "$line\n" unless ($line eq '');
        @data = ();
    }
}

然后

$ perl blocktab2csv.pl intable.txt > output.csv

输出.csv:

Name;AB;DATA;SOME;IF;DATE(UTC)
Marra Carolina Odoriz Dolman;36737202;098787267;45;-;2019-07-09T10:35:50.289Z
-;53959997;098543650;30;-;2019-07-09T12:02:36.746Z
Vic Velazquez;33577915;096638025;-;6000;2019-07-09T12:40:17.754Z
Gabriela Letacia Cararallo Vacchetzi;43132876;091322398;30;-;2019-07-09T12:40:40.887Z

这假定您的字段中没有分号。不过,很容易修改以处理它们。

【讨论】:

  • 斯科特!现在对原始数据源进行了一些更改,我在名称字段中有 2 行和 3 行但没有管道和下划线的新数据源,需要知道更改脚本以使这些更改生效,提前致谢! ——
【解决方案2】:

尝试使用 sed,这里有一个非常相似的例子 replace pipes with commas 你的代码看起来更像这样,因为你只有一个管道。

sed 's/|/,/g' input.csv >output.csv

此外,我建议您检查您的文件是否已经包含任何逗号,因为这会导致您出现问题。如果文件中没有由分隔符括起来的字符串,则可能使用制表符来分隔文件。

【讨论】:

  • Patrick 谢谢,但问题是一样的,管道现在变成了分号,但是当我有一行有 2 行时,它会出现一个新的幻像记录,第二行和所有其他字段为空白。
  • 这是结果的样子: ;梅兰妮·维西尼亚·加里亚; 52521723; 093454525; 19; - ; 2019-07-09T22:02:26.139Z; ;德尔加多; ; ; ; ; ;
  • 这告诉我,您的文件永远不会像更换管道那么简单。我同意@shelter 的意见,我会联系您获取文件的任何人或地点。
  • 斯科特!现在对原始数据源进行了一些更改,我在名称字段中有 2 行和 3 行但没有管道和下划线的新数据源,需要知道更改脚本以使这些更改生效,提前致谢!
  • 对原始解决方案进行了一些更改,以获取一个没有管道和四个下划线(如行尾)的新文件,但无法打印所需的正确输出.. 你能对我的更改进行一些观察吗建议一些人进行这项修改?
猜你喜欢
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 2019-05-09
  • 2013-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多