2010-10-27 39 views
8

Tôi có một mảng như thế nàyToán tử thay thế Perl có thể khớp với một phần tử trong một mảng không?

my @stopWords = ("and","this",....) 

văn bản của tôi là trong biến này

my $wholeText = "....and so this is...." 

Tôi muốn để phù hợp với mỗi lần xuất hiện của mỗi phần tử của mảng từ dừng của tôi trong vô hướng wholeText và thay thế bằng không gian .

Một cách để làm điều này là như sau:

foreach my $stopW (@stopWords) 
{ 
    $wholeText =~ s/$stopW/ /; 
} 

này hoạt động và thay thế tất cả các lần xuất hiện của tất cả các từ dừng lại. Tôi chỉ tự hỏi, nếu có cách làm ngắn hơn.

Như thế này:

$wholeText =~ s/@stopWords/ /; 

Trên đây dường như không làm việc mặc dù.

Trả lời

-1
grep{$wholeText =~ s/\b$_\b/ /g}@stopWords; 
+0

này sẽ xoá 'và' trong 'ngàn'. –

+0

@ Jonathan Leffler: cảm ơn vì đã chỉ ra nhưng tôi nghĩ OP cũng không xử lý trường hợp này. :) –

+1

OP có thể muốn nó được xử lý; anh ta có thể muốn tất cả các lần xuất hiện của mỗi từ dừng (trong sự cô lập) bị loại bỏ, không chỉ là lần xuất hiện đầu tiên của mỗi từ. Một giải pháp đầy đủ làm tất cả cùng một lúc. –

3

gì về:

my $qrstring = '\b(' . (join '|', @stopWords) . ')\b'; 
my $qr = qr/$qrstring/; 
$wholeText =~ s/$qr/ /g; 

CONCATENATE tất cả các từ để tạo thành '\b(and|the|it|...)\b'; các dấu ngoặc đơn xung quanh phép nối là cần thiết để cung cấp cho nó một ngữ cảnh danh sách; không có chúng, bạn kết thúc với số lượng từ). Các ký tự '\b' đánh dấu các ranh giới từ và do đó ngăn bạn thay đổi 'nghìn' thành 'Nghìn'. Chuyển đổi thành biểu thức chính quy được trích dẫn; áp dụng nó trên toàn cầu vào chuỗi chủ đề của bạn (để tất cả các lần xuất hiện của tất cả các từ dừng được loại bỏ trong một hoạt động đơn lẻ).

Bạn cũng có thể làm mà không có sự biến '$qr ':

my $qrstring = '\b(' . (join '|', @stopWords) . ')\b'; 
$wholeText =~ s/$qrstring/ /g; 

Tôi không nghĩ rằng tôi muốn chăm sóc để duy trì mã của bất cứ ai cố gắng làm mà không có sự biến' $qrstring'; nó có thể có thể được thực hiện, nhưng tôi không nghĩ rằng nó sẽ rất dễ đọc.

+0

Cảm ơn tất cả các câu trả lời. Tôi đã thử mã của Nikhil Jain và nó đang hoạt động. Nhờ những người khác nữa. U tất cả đá! Cảm ơn! – Radz

5

giải pháp tốt nhất của tôi:

$wholeText =~ s/$_//g for @stopWords; 

Bạn có thể muốn làm sắc nét regexp sử dụng một số \b và khoảng trắng.

3

phiên bản hoang tưởng của tôi:

$wholeText =~ s/\b\Q$_\E\b/ /gi for @stopWords; 

Sử dụng \b để phù hợp với ranh giới từ, và \Q..\E chỉ trong trường hợp bất kỳ của các tệp từ dừng của bạn chứa các ký tự có thể được hiểu là "đặc biệt" bởi động cơ regex.

3

Bạn có thể xem xét sử dụng regex để tạo một regex đơn.

my $regex_str = join '|', map { quotemeta } @stopwords; 
$string =~ /$regex_str/ /g; 

Lưu ý rằng phần quotemeta chỉ đảm bảo rằng mọi ký tự regex đều được thoát đúng cách.

7

Trong khi các giải pháp khác nhau map/for dựa trên sẽ hoạt động, họ cũng sẽ thực hiện xử lý regex chuỗi riêng cho từng từ khóa. Mặc dù đây không phải là vấn đề lớn trong ví dụ được đưa ra, nhưng nó có thể gây ra các vấn đề hiệu suất chính khi văn bản đích và danh sách từ dừng phát triển.

Jonathan Leffler và Robert P đang đi đúng hướng với các đề xuất kết hợp tất cả các từ khóa với nhau thành một regex duy nhất, nhưng một đơn giản là một cách tiếp cận thô và một lần nữa, trở nên kém hiệu quả nếu danh sách từ dừng dài.

Nhập Regexp::Assemble, mà sẽ xây dựng cho bạn một nhiều regex 'thông minh' để xử lý tất cả các trận đấu cùng một lúc - Tôi đã sử dụng nó để tác động tốt với danh sách lên đến 1700 hoặc lâu hơn từ để được kiểm tra chống lại:

#!/usr/bin/env perl 

use strict; 
use warnings; 
use 5.010; 

use Regexp::Assemble; 

my @stopwords = qw(and the this that a an in to); 

my $whole_text = <<EOT; 
Fourscore and seven years ago our fathers brought forth 
on this continent a new nation, conceived in liberty, and 
dedicated to the proposition that all men are created equal. 
EOT 

my $ra = Regexp::Assemble->new(anchor_word_begin => 1, anchor_word_end => 1); 
$ra->add(@stopwords); 
say $ra->as_string; 

say '---'; 

my $re = $ra->re; 
$whole_text =~ s/$re//g; 
say $whole_text; 

những kết quả đầu ra:

\b(?:t(?:h(?:at|is|e)|o)|a(?:nd?)?|in)\b 
--- 
Fourscore seven years ago our fathers brought forth 
on continent new nation, conceived liberty, 
dedicated proposition all men are created equal. 
Các vấn đề liên quan