0

ID 列とフリー テキスト列の 2 つの列を持つ csv ファイルがあります。ID 列には 16 文字の英数字 ID が含まれていますが、セルに存在する唯一のデータではない可能性があります: 空白のセル、16 文字の ID のみを含むセル、または多数のものを含むセルである可能性がありますその中に埋め込まれた次の-「user_id = xxxxxxxxxxxxxxxx」

私が望むのは、どのセルからでも16文字のIDを何らかの形で抽出することです。したがって、次のことを行う必要があります: (a) 空白のセルを無視する (b) セルの内容が、間にスペースのない連続した 16 文字の文字列のみの場合は、セル全体の内容を抽出する (c) パターン「user_id=」を探してから、その直後の 16 文字

パターン マッチングや文字列の検索/置換などの Perl スクリプトはたくさんありますが、同じ列でさまざまな種類の解析/パターン検索と抽出を次々に実行する方法がわかりません。すでにお気づきかもしれませんが、私は Perl にかなり慣れていません。

4

4 に答える 4

1

(1) 何も含まない行、または仕様に一致しない行をスキップしたいというご要望を承りました。(2) セルの唯一のコンテンツである場合は、16 個の非スペース文字をキャプチャします。(3) リテラル パターン "user_id=" に続く 16 個の非スペース文字をキャプチャします。

スペース文字もキャプチャしても問題ない場合は、それらが " user_id=" リテラルに続く場合は、適切な場所で に\S変更できます。.

私のソリューションでは、Text::CSVを使用して、CSV ファイルの処理の詳細を処理します。これを行う方法は次のとおりです。

use strict;
use warnings;
use autodie;
use open ':encoding(utf8)';
use utf8;
use feature 'unicode_strings';
use Text::CSV;
binmode STDOUT, ':utf8';

my $csv = Text::CSV->new( {binary => 1} ) 
    or die "Cannot use CSV: " . Text::CSV->error_diag;

while( my $row = $csv->getline( \*DATA ) ) {
    my $column = $row->[0];
    if( $column =~ m/^(\S{16})$/ || $column =~ m/user_id=(\S{16})/ ) {
        print $1, "\n";
    }
}

__DATA__
abcdefghijklmnop
user_id=abcdefghijklmnop
abcd fghij lmnop
randomdatAuser_id=abcdefghijklmnopMorerandomdata
user_id=abcd fghij lmnop
randomdatAuser_id=abcd fghij lmnopMorerandomdata

あなた自身のコードでは、ファイルハンドルを使用していないでしょうが、ファイルを開く方法はすでにDATA知っていると思います。

CSV は一見シンプルな形式です。ただし、その高い可読性と構文解析の単純さを混同しないでください。CSV を扱う場合は、実証済みのモジュールを使用して列を抽出することをお勧めします。他のソリューションは、引用符が埋め込まれたコンマ、エスケープされたコンマ、アンバランスな引用符、および脳がその場で修正するその他の不規則性に失敗する可能性がありますが、純粋な正規表現ソリューションは脆弱になります.

于 2012-07-12T19:44:52.353 に答える
0

たとえば、次の例では 2 行目と 3 行目のみが有効であるため、cell1 (column1) では

  • 正確に 16 文字の長さの文字列、または
  • 「user=16charshere」があります

その他は無効です。

use 5.014;
use warnings;

while(<DATA>) {
    chomp;
    my($col1, @remainder) = split /\t/;
    say $2 if $col1 =~ m/^(|user=)(.{16})$/;
}
__DATA__
ToShort col2    not_valid
a123456789012345    col2    valid
user=b123456789012345   col2    valid
TooLongStringHereSoNotValidOne  col2    not_valid

この例では、列はタブで区切られています。

于 2012-07-12T19:40:46.490 に答える
0

さて、基本的なファイルと、必要なことを実行できる正規表現コマンドを使用してセットアップできます (perl に慣れていない人向けの基本的な形式で)。

use strict;
use warnings;

open FILE "<:utf8", "myfile.csv";
#"slurp" the file into an array, each element is a line
my @lines = <FILE>;
my @idArray;
foreach my $line (@lines){
    #make two captures, the first we can ignore and both are optional
    $line =~ /^(user_id=|)([A-Za-z0-9]{16}|),/;
    #for display purposes, this is just the second captured group
    my $id = $2;
    #if the group actually has something in it, add it to your final array
    if($id){ push @idArray, $id; }
}
于 2012-07-12T19:14:11.810 に答える
-1

(a) ソリューションのテストに使用できるいくつかのサンプル データを提供し、(b) この問題に対してこれまでに作成したコードを提供してみてください。

splitただし、おそらく、テーブルのすべての行を調べてからフィールドに移動し、特定のフィールドですべての操作を実行し、ビジネス ロジックを実行してから、すべてを書き戻したいと思うでしょう。

問題 (c) は次のように解決されます。$idField =~ /user_id=(.{16})/; my $id = $1;

user_id が常に行の先頭に表示される場合、これでうまくいきます。for (<FILE>) {/^user_id=(.{16})/; ...}

于 2012-07-12T19:12:57.287 に答える