如何在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
答案 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