0

Perl では、テキストの段落からすべての単語の配列を作成しようとしています。

今、私は使用しています@tokens = split /[^\w']+/, $mytext;

すべての英数字の単語を取得しているようですが、すべての句読点をアンダースコア以外の単語と見なしたいと考えています。例

hi. my name is first_last ...

言葉に変わるはずです:こんにちは、。、私の、名前、は、first_last、です。、 。、 。

全部で9語。

どうやってやるの?句読点で分割しようとしましたが、句読点は保存されませんでした。

4

5 に答える 5

2

多くの場合、分割するよりも一致させる方が簡単です。一連の単一引用符/単語文字(_を含む)またはその他の空白以外の単一文字と一致させたいようです。

my $mytext = 'hi. my name is first_last ...';
my @tokens = $mytext =~ /([\w']+|\S)/g;
print join( ' , ',  @tokens ),"\n";

生成:

hi , . , my , name , is , first_last , . , . , .

[\w']任意の単語文字(文字、数字、またはアンダースコア)または一重引用符を許可する文字クラスです。他の文字を追加することもできますが、一部は\-エスケープする必要がある場合があります(たとえば[\w'\-]、ハイフンを追加するため)。

于 2013-01-31T18:55:52.367 に答える
1

これらがあなたの言葉なら

hi. my name is first_last ...
11  22 3333 44 5555555555

そして、これらはあなたのセパレーターではありません

hi. my name is first_last ...
  11  22   33 4          5555

そうすれば、あなたは実際に単語を分割していません(そしてsplitおそらくうまく機能しないでしょう)。実際にはトークナイザーが必要です。

トークナイザーを構築する一般的な方法は次のとおりです。

my @tokens;
for ($mytext) {
   /\G \s+ /xgc;
   if (/\G ( [\w']+   ) /xgc) { push @tokens, $1; redo; }
   if (/\G ( [^\s\w'] ) /xgc) { push @tokens, $1; redo; }
   die "Bad code";
}

しかし、それを単純化することはできます。

my @tokens = $mytext =~ /\G\s*([\w']+|[^\S\w'])/g;

あるいは

my @tokens = $mytext =~ /\G\s*([\w']+|\S)/g;
于 2013-01-31T19:45:58.320 に答える
0
perldoc -f split 
==>
    split /PATTERN/,EXPR,LIMIT
    split /PATTERN/,EXPR
    split /PATTERN/
    split   Splits the string EXPR into a list of strings and returns that
            list. By default, empty leading fields are preserved, and empty
            trailing ones are deleted. (If all fields are empty, they are
            considered to be trailing.)
    ...
            If the PATTERN contains parentheses, additional list elements
            are created from each matching substring in the delimiter.

                split(/([,-])/, "1-10,20", 3);

            produces the list value

                (1, '-', 10, ',', 20)
    ...

追加した:

コード内:

my $inp   = 'hi. my name is first_last ...';
my @parts = split /(\W)/, $inp;
printf "%d parts: (%s)\n", scalar @parts, join('), (', @parts);
@parts = grep {$_ gt ' '} @parts;
printf "%d parts: (%s)\n", scalar @parts, join('), (', @parts);

出力:

18 parts: (hi), (.), (), ( ), (my), ( ), (name), ( ), (is), ( ), (first_last), ( ), (), (.), (), (.), (), (.)
9 parts: (hi), (.), (my), (name), (is), (first_last), (.), (.), (.)
于 2013-01-31T18:57:44.820 に答える
0

ysth のアイデアの拡張:

my $mytext = 'hi. My name22222 is first_last!? 2,0 #@/';
my @tokens = $mytext =~ /([a-zA-Z_]+|[0-9]+|[.?!,])/g;
print join ":", @tokens,"\n";

出力:

hi:.:My:name:22222:is:first_last:!:?:2:,:0:

これは、\w と \S の使用を避けるため、理解しやすいです。\w は混乱を招く _ を含んでいるので、あなたが思っている以上にカバーしています。\S は、句読点以外にも一致します。

上記は | の使用方法を示しています。単語を構成できる文字のセットを分割し、文字を明示的に定義します。単語の一部ではない「ガベージ」は除外されます。

于 2013-01-31T20:36:33.910 に答える
0

1 つのアプローチは、ルックアラウンド アサーションを使用することです。空白で (1) を分割します。(2) 前の文字が入っていたときはいつでも[^\w'](文字列の終わりを除く)。(3)次の文字が入っているときはいつでも[^\w'](文字列の開始時を除く)、次のように書くことができます:

@tokens = split /\s+|(?<=[^\w'])|(?=(?!^)[^\w'])/, $mytext;
于 2013-01-31T18:50:03.923 に答える