2

親愛なる世界の仲間の perl マスター~!

あなたの助けが必要です。

次のような文字列ファイル A と数値ファイル B があります。

ファイル A:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

...200まで続きます。

ファイル B:

3, 6, 2, 5, 6, 1, ... 2 

(配列内の合計 200 の数字)

次に、ファイル B の数字を使用して、各文字列を開始位置からファイル B の文字数まで切り取りたいと思います。

たとえば、ファイル B は 3、6、2 ... で始まります。

ファイルAは

AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

このような。

そう。これはこれまでの私のコードです...

use strict;

if (@ARGV != 2) {
    print "Invalid usage\n";
    print "Usahe: perl program.pl [num_list] [string_file]\n";
    exit(0);
}

my $numbers=$ARGV[0];
my $strings=$ARGV[1];
my $i;

open(LIST,$number);
open(DATA,$strings);

my @list = <LIST>;
my $list_size = scalar @sp_list;


for ($i=0;$i<=$list_size;$i++) {
    print $i,"\n";
    #while (my $line = <DATA>) {    
    }   


close(LIST);
close(DATA);

文字列と数値が 200 であるため、配列をスカラー値に変更して、すべての文字列のすべての数値で機能するようにしました。

私はこれに取り組んでいます。私は pos 関数を使用することを想定していますが、各数値を各文字列と一致させる方法がわかりません。最初に文字列を読んでいますか?または、結果を達成するためにこれを実行する必要がある時間を知るために for を使用しますか?

あなたの助けは大歓迎です!

ありがとうございました。

私も取り組んでいきます。フィードバックが必要です。

4

5 に答える 5

5

使うのはいいし、使うstrictべきwarningsです。その他の注意事項:

の戻り値をチェックして、open失敗していないことを確認する必要があります。また、 の 3 つの引数形式をopen使用し、レキシカル ファイル ハンドルを使用する必要があります。特にコマンド ライン引数を処理する場合は、セキュリティ リスクが生じます。

open my $listfh, "<", $file or die $!;

安全対策を講じる必要がある場合があります

use ARGV::readonly;

map数のリストはステートメントで簡単に作成できます。数値がカンマ区切りのリストにあると仮定します。

my @list = map split(/\s*,\s*/), <$listfh>;

これにより、入力行がコンマで分割され、余分な空白が取り除かれます。

入力ファイルを読み取るときは、カウンター変数を使用する必要はありません。あなたは簡単に行うことができます

open my $inputfh, "<", $file or die $!;
while (<$inputfh>) {
    my $length = shift @list;   # these are your numbers
    chomp;                      # remove newline 
    my $string = substr($_, 0, -$length);  # negative length on substr
    print "$string\n";
}

substr の負の長さにより、文字列の末尾から多くの文字が離れます。

以下は、これらの原則を示す実際のワンライナーです。

perl -lwe '$f = pop;                            # save file name for later
           @nums = map split(/\s*,\s*/), <>;    # process first file
           push @ARGV, $f;                      # put back file name
           while (<>) { 
                my $len = shift @nums; 
                chomp; 
                print substr($_,0,-$len); 
           }' fileb.txt filea.txt

出力:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEE

操作によるファイル名引数の暗黙的なオープンの使用に注意してください@ARGV。また、スイッチで改行を処理し-lます。

于 2013-02-15T10:28:51.223 に答える
3

これが私の提案です。これにより、呼び出しuse autodieのステータスを明示的にチェックする必要がなくなり、すべてのファイルが一度に読み取られるようopenに、一時的に定義解除$/(入力レコード セパレータ) が行われます。このファイルに常に 1 行だけが含まれるかどうかは明確ではありません。その場合は省略できます。num_listlocal $/

数値は、正規表現を使用してテキストから抽出され/\d+/g、入力内のすべての数字の文字列をリストとして返します。

の 2 番目のパラメーターsubstrは、必要な部分文字列の開始位置であり、負の数を使用すると、文字列の先頭ではなく末尾からカウントされます。3 番目のパラメーターは部分文字列の文字数で、4 番目のパラメーターはターゲット変数内のその部分文字列を置き換える文字列です。そのため、末尾から始まるsubstr $data, -$n, $n, ''長さの文字の部分文字列を空の文字列に置き換えます-つまり、それを削除します。$n$n

文字列の先頭から指定された数の文字を削除することが意図されている場合は、substr $data, 0, $n, ''代わりに書くこと に注意してください。

use strict;
use warnings;
use autodie;

unless (@ARGV == 2) {
  print "Usage: perl program.pl [num_list] [string_file]\n";
  exit;
}

my @numbers;
{
  open my $listfh, '<', $ARGV[0];
  local $/;
  my $numbers = <$listfh>;
  @numbers = $numbers =~ /\d+/g;
};


open my $datafh, '<', $ARGV[1];

for my $i (0 .. $#numbers) {
  print "$i\n";
  my $n = $numbers[$i];
  my $data = <$datafh>;
  chomp $data;
  substr $data, -$n, $n, '';
  print "$data\n";
}   
于 2013-02-15T10:43:52.120 に答える
2

これが私がそれを行う方法です。substrは、文字列の一部を削除する関数です。あなたの例から、最初または最後に文字を削除するかどうかは明確ではありません。両方の代替方法を次に示します。

#!/usr/bin/perl
use warnings;
use strict;

if (@ARGV != 2) {
    die "Invalid usage\n"
        . "Usage: perl program.pl [num_list] [string_file]\n";
}

my ($number_f, $string_f) = @ARGV;

open my $LIST, '<', $number_f or die "Cannot open $number_f: $!";
my @numbers = split /, */, <$LIST>;
close $LIST;

open my $DATA, '<', $string_f or die "Cannot open $string_f: $!";
while (my $string = <$DATA>) {
    substr $string, 0, shift @numbers, q(); # Replace the first n characters with an empty string.

    # To remove the trailing portion, replace the previous line with the following:
    # my $n = shift @numbers;
    # substr $string, -$n-1, $n, q();

    print $string;
}

の戻り値をチェックしていませんでしたopen。常にそれを行うことを忘れないようにしてください。

変数を使用する前に変数を宣言しないでください ($iここ)。

必要がない場合は、C スタイルのforループを使用しないでください。彼らはフェンスポストエラーを起こしやすい.

于 2013-02-15T10:26:23.607 に答える
0

使用できますsubstr()

use strict;
use warnings;

if (@ARGV != 2) {
    print "Invalid usage\n";
    print "Usage: perl program.pl [num_list] [string_file]\n";
    exit(0);
}

my $numbers=$ARGV[0];
my $strings=$ARGV[1];

open my $list, '<', $numbers or die "Can't open $numbers: $!";
open my $data, '<', $strings or die "Can't open $strings: $!";

chomp(my $numlist = <$list>);
my @numbers = split /\s*,\s*/,$numlist;
for my $chop_length (@numbers)
{
   my $data = <$data> // die "not enough data in $strings";
   print substr($data,0,length($data)-$chop_length)."\n";
}
于 2013-02-15T10:17:43.163 に答える
0

あなたの仕様は、「...ファイルBの開始位置から文字数まで各文字列をカットする」ことを望んでいると言っています。文字列の先頭と末尾のどちらの文字を切り取るかが完全に明確ではないというチョロバ に同意します。ただ、 「…先頭から…」と言うと先頭から文字を抜きたいと思われがちですが、 のような文字列があるとわかりやすいです。ABCDEFGHIJKLMNOPQRSTUVWXYZ012345

このオプションは、他のソリューションほど自己文書化されていませんが、それについての説明は次のとおりです。

use strict;
use warnings;

@ARGV == 2 or die "Usage: perl program.pl [num_list] [string_file]\n";

open my $fh, '<', pop or die "Cannot open string file: $!";
chomp( my @str = <$fh> );

local $/ = ', ';

while (<>) {
    chomp;
    print +( substr $str[ $. - 1 ], $_ ) . "\n";
}

文字列:

ABCDEFGHIJKLMNOPQRSTUVWXYZ012345
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

数字:

3, 6, 2, 5, 6

出力:

DEFGHIJKLMNOPQRSTUVWXYZ012345
BBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEEEEEEEE

文字列のファイル名はpop省略され@ARGV(明示的な引数が使用されていないため) 、文字列を に読み込むために にpop渡されます。レコード セパレータは に設定されているため、数字のみが残ります。の現在の行番号は、対応する要素へのインデックスの一部として使用され、それ以降の文字列内の残りの文字が出力されます。open@str', 'chomp$.@strn

于 2013-02-16T00:44:49.413 に答える