每个字段的字符位置

时间:2014-03-19 11:14:19

标签: perl awk nawk

如何在field5及以上的单词中表示1的位置(仅考虑冒号后的1s);从右到左计数。

输入:

TT-124 06-03-14 08-02-10 FAS   CAT1:10
TT-125-1 05-03-14 10-06-08 CAS   CAT2:1010 FAT1:10000
TT-125-3 07-03-14 11-02-06 FAS   FAT1:1101
SS-120-1 05-03-14 09-04-07 FAS   CAT3:100000
AA-121-0 06-03-14 08-03-06 CAS   FAT2:11 CAT1:101100

输出:

TT-124 06-03-14 08-02-10 FAS   CAT1:1
TT-125-1 05-03-14 10-06-08 CAS   CAT2:3 CAT2:1 FAT1:4
TT-125-3 07-03-14 11-02-06 FAS   FAT1:0 FAT1:2 FAT1:3
SS-120-1 05-03-14 09-04-07 FAS   CAT3:5
AA-121-0 06-03-14 08-03-06 CAS   FAT2:0 FAT2:1 CAT1:2 CAT1:3 CAT1:5

我尝试过以下脚本(由某人建议)在cygwin中运行,但在使用nawk或/ usr / xpg4 / bin / awk的Solaris 10上不起作用 我怎样才能在solaris中实现?

awk '{for(i = 5; i <= NF; i++) {split($i, a, ":"); $i = ""; split(a[2], b, "");
  for(j = 1; j <= length(b); j++) {if(b[j] == 1)
    {$i = ($i == "") ? (a[1] ":" length(b) - j) : ($i FS a[1] ":" length(b) - j)}}};
  print $0}' file

3 个答案:

答案 0 :(得分:3)

使用看起来像(非常难以辨认)其他人写的单线的缺点是,当它破坏时你很难修复。我编写了一些易于理解且易于维护的Perl代码。

它基本上使用正则表达式来拆分你的字符串,该正则表达式被硬编码为首先忽略(匹配和打印)4个空格分隔的数据字段,然后在其后提取相关数据。这可以更具体,但你没有指定你的数据有什么格式,如果有的话,所以这是我现在要做的最具体的。

然后它需要@-数组$-[0]的第一个元素来查找每个目标字符串的数字字符串中每个1的位置,并根据名称构建新的字符串,以及每个数字匹配。

use strict;
use warnings;

while (<DATA>) {
    my ($pre, $data) = /^((?:\S+\s+){4})(.+)/;   # capture using regex
    print $pre;                                  # print original prefix string
    my @list;
    for (split ' ', $data) {                     # the list of CAT2:11 pairs
        my ($name, $num) = split /:/;            # separate name and number
        $num = reverse $num;                     # reverse order of numbers
        while ($num =~ /1/g) {                   # extract position of each "1" 
            push @list, "$name:$-[0]";           # make the new string with name
        }
    }
    print "@list\n";                             # print list separated by space
}

__DATA__
TT-124 06-03-14 08-02-10 FAS   CAT1:10
TT-125-1 05-03-14 10-06-08 CAS   CAT2:1010 FAT1:10000
TT-125-3 07-03-14 11-02-06 FAS   FAT1:1101
SS-120-1 05-03-14 09-04-07 FAS   CAT3:100000
AA-121-0 06-03-14 08-03-06 CAS   FAT2:11 CAT1:101100

<强>输出:

TT-124 06-03-14 08-02-10 FAS   CAT1:1
TT-125-1 05-03-14 10-06-08 CAS   CAT2:1 CAT2:3 FAT1:4
TT-125-3 07-03-14 11-02-06 FAS   FAT1:0 FAT1:2 FAT1:3
SS-120-1 05-03-14 09-04-07 FAS   CAT3:5
AA-121-0 06-03-14 08-03-06 CAS   FAT2:0 FAT2:1 CAT1:2 CAT1:3 CAT1:5

<强>用法:

要尝试输出代码,请将文件句柄<DATA>更改为<>并使用:

perl script.pl input.txt > output.txt

当然,重定向到输出文件是可选的。

答案 1 :(得分:1)

试试这个代码段。

#!/usr/bin/perl

use strict;
use warnings;

foreach my $line (<DATA>) {
  my @args = split /\s+/, $line;

  foreach my $arg (@args) {
    if (not $arg =~ /([A-Z]+\d+)\:([0-1]+)/) {
      print "$arg ";
      next;
    }

    my @bits = split //, $2;
    my $j = $#bits;
    for my $i (0 .. $#bits) {
      print "$1:$j " if $bits[$i];
      $j--;
    }

  }
  print "\n";
}

__DATA__
TT-124 06-03-14 08-02-10 FAS   CAT1:10
TT-125-1 05-03-14 10-06-08 CAS   CAT2:1010 FAT1:10000
TT-125-3 07-03-14 11-02-06 FAS   FAT1:1101
SS-120-1 05-03-14 09-04-07 FAS   CAT3:100000
AA-121-0 06-03-14 08-03-06 CAS   FAT2:11 CAT1:101100

输出:

TT-124 06-03-14 08-02-10 FAS CAT1:1 
TT-125-1 05-03-14 10-06-08 CAS CAT2:3 CAT2:1 FAT1:4 
TT-125-3 07-03-14 11-02-06 FAS FAT1:3 FAT1:2 FAT1:0 
SS-120-1 05-03-14 09-04-07 FAS CAT3:5 
AA-121-0 06-03-14 08-03-06 CAS FAT2:1 FAT2:0 CAT1:5 CAT1:3 CAT1:2 

答案 2 :(得分:1)

您的输入数据与所需输出不一致。你说你想要CAT2:3 CAT2:1作为第二行,但这不是从右到左的顺序,并且与其他输出行不匹配,所以我认为这是一个错误。

我认为这个程序是你需要的。它期望输入文件的路径作为命令行上的参数,并将输出打印到STDOUT。

use strict;
use warnings;

while (<>) {

  my @fields = split;

  for (my $i = $#fields; $i >= 4; --$i) {
    my ($prefix, $suffix) = split /:/, $fields[$i];
    my @positions;
    push @positions, length($suffix) - $-[0] - 1 while $suffix =~ /1/g;
    my @expansions = map "$prefix:$_", reverse @positions;
    splice @fields, $i, 1, @expansions;
  }

  print "@fields\n";
}

<强>输出

TT-124 06-03-14 08-02-10 FAS CAT1:1
TT-125-1 05-03-14 10-06-08 CAS CAT2:1 CAT2:3 FAT1:4
TT-125-3 07-03-14 11-02-06 FAS FAT1:0 FAT1:2 FAT1:3
SS-120-1 05-03-14 09-04-07 FAS CAT3:5
AA-121-0 06-03-14 08-03-06 CAS FAT2:0 FAT2:1 CAT1:2 CAT1:3 CAT1:5