1

我编写了一个 perl 脚本,将 3 列拆分为标量,并使用正则表达式替换第二列中的各种值。这部分工作正常,如下所示。不过,我想做的是将第一列 ($item_id 更改为一系列序号,这些序号在 $item_id 的原始(数字)值更改时重新启动。

例如:123
123
123
123
2397
2397
2397
2397
8693
8693
8693
8693

将更改为这样的内容(在列中):

1 2 3 4 1 2 3 4 1 2 3 4

这可以替换第一列或成为新的第四列。我知道我可以通过一系列 if-else 语句来做到这一点并尝试了这个,但这似乎与我已经为我工作的 while 过程不太匹配。- 谢谢,汤姆·谢泼德

open(DATA,"< text_to_be_processed.txt");
while (<DATA>)
{
chomp;
my ($item_id,$callnum,$data)=split(/\|/);
$callnum=~s/110/\%I/g;
$callnum=~s/245/\%T/g;
$callnum=~s/260/\%U/g;
print "$item_id\t$callnum\t$data\n";
}   #End while
close DATA;
4

3 回答 3

1

基本步骤是:

在循环之外声明计数器和一个保存前一个的变量$item_id

在循环中,你做了三件事:

  1. $item_id如果当前与前一个不同,则将计数器重置为 1 ,否则将其增加
  2. 使用那个计数器,例如打印它
  3. 记住之前的值

使用代码,这可能看起来与此类似(未经测试):

my ($counter, $prev_item_id) = (0, '');
while (<DATA>) {
  # do your thing
  $counter      = $item_id eq $prev_item_id ? $counter + 1 : 1;
  $prev_item_id = $item_id;
  print "$item_id\t$counter\t...\n";
}
于 2012-10-10T14:50:48.207 回答
1

这比你问的更进一步......

  • 使用词法文件句柄
  • [autodie] 使 open 自动抛出错误
  • 使用表格替换呼叫号码
  • 不要假设数据按项目 ID 排序

这是代码。

use strict;
use warnings;
use autodie;

open(my $fh, "<", "text_to_be_processed.txt");

my %Callnum_Map = (
    110         => '%I',
    245         => '%T',
    260         => '%U',
);

my %item_id_count;
while (<$fh>) {
    chomp;
    my($item_id,$callnum,$data) = split m{\|};

    for my $search (keys %Callnum_Map) {
        my $replace = $Callnum_Map{$search};
        $callnum =~ s{$search}{$replace}g;
    }


    my $item_count = ++$item_id_count{$item_id};

    print "$item_id\t$callnum\t$data\t$item_count\n";
}

通过使用散列,它不会假定数据是按项目 ID 排序的。所以如果看到...

123|foo|bar
456|up|down
123|left|right
789|this|that
456|black|white
123|what|huh

它会产生...

1
1
2
1
2
3

假设您想要计算在整个文件中看到项目 id 的次数,这将更加健壮。如果您想连续看到多少次,请使用 Mortiz 的解决方案。

于 2012-10-10T15:07:51.840 回答
0

这是你想要的?

open(DATA,"< text_to_be_processed.txt");
my $counter = 0;
my $prev;

while (<DATA>)
{
chomp;
my ($item_id,$callnum,$data)=split(/\|/);
$callnum=~s/110/\%I/g;
$callnum=~s/245/\%T/g;
$callnum=~s/260/\%U/g;
++$counter;
$item_id = $counter;
#reset counter if $prev is different than $item_id
$counter = 0 if ($prev ne $item_id );
$prev = $item_id;
print "$item_id\t$callnum\t$data\n";
}   #End while
close DATA;
于 2012-10-10T14:51:07.467 回答