0

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

输入:

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
4

3 回答 3

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

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

于 2014-03-19T12:04:09.043 回答
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 
于 2014-03-19T11:33:03.360 回答
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
于 2014-03-19T11:33:23.667 回答