采用多个标题(行匹配条件)并转换为列

时间:2015-06-17 09:12:03

标签: bash perl command-line awk sed

您好,我有一个文件,其中包含多个标题,我需要将其转换为列值。该文件如下所示:

Day1
1,Smith,London
2,Bruce,Seattle
5,Will,Dallas
Day2
1,Mike,Frisco
4,James,LA

我希望文件最终看起来像这样:

Day1,1,Smith,London
Day1,2,Bruce,Seattle
Day1,5,Will,Dallas
Day2,1,Mike,Frisco
Day2,4,James,LA

该文件在名称之前没有连续数字,并且在" Day"之后它没有相同数量的记录。头。 有没有人对如何使用命令行完成此任务有任何想法?

7 个答案:

答案 0 :(得分:6)

在awk中

awk -F, 'NF==1{a=$0;next}{print a","$0}' file

检查字段数是否为1,如果是,则设置变量并跳过下一个块。

对于没有1个字段的每一行,它会打印保存的变量和行

并在sed

sed -n '/,/!{h};/,/{x;G;s/\n/,/;p;s/,.*//;x}' file

为MrBones疯狂骑行打破了。

sed -n '

        /,/!{h};       // If the line does not contain a comma overwrite buffer with line

       /,/{            // If the line contains a comma, do everything inside the brackets
           x;          // Exchange the line for the held in buffer
           G;          // Append buffer to line
           s/\n/,/;    // Replace the newline with a comma
           p;          // Print the line
           s/,.*//;    // Remove everything after the first comma
           x           // exchange line for hold buffer to put title back in buffer for the next line.
          }' file      // The file you are using

本质上它保存了没有,的行,即标题。然后,如果它不是标题,它将使用保存的标题切换当前行,并将现在切换的行追加到标题的末尾。因为它附加了换行符,然后下一个语句用逗号替换它。然后打印该行。 NExt恢复标题,删除它之后的所有内容并将其交换回缓冲区,为下一行做好准备。

答案 1 :(得分:3)

sed '/^Day/ {h;d;}
     G;s/\(.*\)\n\(.*\)/\2,\1/
    ' YourFile
  • posix compliance
  • 之后,如果不是至少1 数据,则不打印任何内容
  • 白线被视为数据

awk '{if ( $0 ~ /^Day/ ) Head = $0; else print Head "," $0}' YourFile

  • 使用Day作为段落分隔符,将内容用作标题,以便在以下行中使用

答案 2 :(得分:2)

Perl解决方案:

#! /usr/bin/perl
use warnings;
use strict;

my $header;
while (<>) {                # Read line by line.
    if (/,/) {              # If the line contains a comma,
        print "$header,$_"; # prepend the header.
    } else {
        chomp;              # Remove the newline.
        $header = $_;       # Remember the header.
    }
}

答案 3 :(得分:1)

<强>的Perl

$ perl -F, -wlane ' if(@F eq 1){$s=$F[0]; next}print "$s,$_"' file
Day1,1,Smith,London
Day1,2,Bruce,Seattle
Day1,5,Will,Dallas
Day2,1,Mike,Frisco
Day2,4,James,LA

答案 4 :(得分:1)

另一个sed版本

sed -n '/Day[0-9]\+/{h;b end};{G;s/\(.*\)\n\(.*\)/\2,\1/;p;:end}'

答案 5 :(得分:1)

这个Perl单行程序将按您的要求执行。它需要Perl v5.14或更高版本

perl -ne'tr/,// ? print $c,$_ : ($c = s/\s*\z/,/r)' myfile.txt

对于早期版本的perl,请使用

perl -ne'tr/,// ? print $c,$_ : ($c = $_) =~ s/\s*\z/,/' myfile.txt

<强>输出

Day1,1,Smith,London
Day1,2,Bruce,Seattle
Day1,5,Will,Dallas
Day2,1,Mike,Frisco
Day2,4,James,LA

答案 6 :(得分:0)

另一个perl示例 - 这次使用$/来分隔每条记录。

use strict;
use warnings;

local $/ = "Day";

while (<>) {
    next unless my ($num) = m/^(\d+)/;
    for ( split /\n/ ) {
        print "Day${num},$_\n" if m/,/;
    }
}