如何用序列号替换行标识符?

时间:2012-10-10 14:40:19

标签: perl loops split

我编写了一个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;

3 个答案:

答案 0 :(得分:1)

基本步骤是:

在循环外部声明计数器和一个包含前一个$item_id的变量。

在循环内你做三件事:

  1. 如果当前$item_id与前一个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"; } 不同,则将计数器重置为1,否则将其增加
  2. 使用该计数器,例如打印它
  3. 记住以前的值
  4. 使用代码,这看起来与此类似(未经测试):

    {{1}}

答案 1 :(得分:1)

这比你要求的更进一步......

  • 使用lexical filehandles
  • [autodie]自动打开错误
  • 使用表
  • 替换呼叫nums
  • 不要假设数据按项目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的解决方案。

答案 2 :(得分: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;