0

以下を含むテストファイル「from.xml」があります。

<target>

<promptlist>
    <prompt address="EXA112" time="00:11:20.00">This is what I want to see first.second</prompt>
    <prompt address="EXA222" time="00:22:20.00">This is what I want to see second</prompt>
</promptlist>
</target>
<target>
<promptlist>
    <prompt address="EXA444" time="00:44:40.00">This is what I want to see fourth</prompt>
    <prompt address="EXA333" time="00:33:30.00">This is what I want to see third</prompt>
    <prompt address="EXA555" time="00:55:50.00">This is what I want to see fifth</prompt>
    <prompt address="EXA111" time="00:11:10.00">This is what I want to see first</prompt>
    <prompt address="EXA666" time="00:66:60.00">This is what I want to see sixth</prompt>
</promptlist>
</target>

ファイルに対してスクリプトを実行すると、次のように正しく生成されます。

00:11:20.00  EXA112  This is what I want to see first.second


00:22:20.00  EXA222  This is what I want to see second


00:44:40.00  EXA444  This is what I want to see fourth


00:33:30.00  EXA333  This is what I want to see third


00:55:50.00  EXA555  This is what I want to see fifth


00:11:10.00  EXA111  This is what I want to see first


00:66:60.00  EXA666  This is what I want to see sixth

上記のように、これは私が目指していたものですが、実際のアプリケーションと同様に、時間は順不同です。この出力をソートする方法はありますか? 私は検索しましたが、明確なものは何も思いつきません。私はこれを作成しました。私はプログラミングと特にPerlの初心者です。時系列で出力する行が必要です。前もって感謝します。

#!/usr/bin/perl
use strict;                             
use warnings;                               
use diagnostics -verbose;                       

my $filename = $ARGV [0];                       
open( my $fh, '<', $filename ) or die "Can't open $filename: $!";       
while ( my $line = <$fh> ) {                        
if ( $line =~ /\<prompt / ) {                       

    if ( $line =~ /time=\"(.+?)\"/ ) {                                
    print"\n $1  ";                                                         
if ( $line =~ /address=\"(.+?)\"/ ) {               
    print"$1  ";                    
if ( $line =~ /\>(.+?)\</ ) {       
    print"$1\n\n ";     
    }
   }
  }  
 }
}
close $fh;
4

3 に答える 3

1

印刷する代わりに、配列に格納し、最初に並べ替えます

于 2013-01-28T04:51:32.643 に答える
1

保存、ソート、出力。

my @data;
while ( <$fh> ) {
   if ( /<prompt / ) {
       if ( /time="([^"]+)"/ ) {
          my $time = $1;

          if ( /address="([^"]+)"/ ) {
             $addr = $1;

             if ( />([^<]+)</ ) {
                push @data, "$time $addr $1\n\n\n";
             }
          }
       }
   }
}

print for sort @data;

その他の変更:

  • インデントを修正しました。
  • おそらく、以前に改行を印刷するのを忘れたため、行末の 1 つが奇妙な場所に印刷されていました。
  • 非貪欲修飾子の使用を削除しました。私はそれが嫌いです; それはただ驚きにつながるだけです。
  • $lineコードを不必要に長くする の使用を削除しました。
  • たくさんの無駄を削除しました\

とはいえ、独自のスラップダッシュ バージョンを作成する代わりに、適切な XML パーサーを使用するのと同じくらい簡単です。

use XML::LibXML qw( );

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($ARGV[0]);
my $root = $doc->documentElement();

my @data;
for my $prompt_node ($root->findnodes('/target/promptlist/prompt')) {
   my $time   = $prompt_node->getAttribute('time');
   my $addr   = $prompt_node->getAttribute('address');
   my $prompt = $prompt_node->textContent();
   push @data, "$time $addr $prompt\n\n\n";
}

print for sort @data;
于 2013-01-28T05:01:18.180 に答える
0

sort ルーチンで sort を使用できます。

#!/usr/bin/perl

use strict;
use warnings;

print "Before sort:\n";
my @s = ("00:22:20.00  EXA222  This is what I want to see second", "00:11:20.00  EXA112  This is what I want to see first.second");
print "$s[0]\n";
print "$s[1]\n";

@s = sort {substr($a, 0, 11) cmp substr($b, 0, 11)}(@s);

print "After sort:\n";
print "$s[0]\n";
print "$s[1]\n";

それは印刷します:

Before sort:
00:22:20.00  EXA222  This is what I want to see second
00:11:20.00  EXA112  This is what I want to see first.second
After sort:
00:11:20.00  EXA112  This is what I want to see first.second
00:22:20.00  EXA222  This is what I want to see second
于 2016-09-27T12:19:31.217 に答える