2009-07-15 9 views
8

私のプログラムは、他のプログラムのソースコードを読み、使用されたSQLクエリに関する情報を収集します。私は部分文字列を得ることに問題があります。Perlでは、マッチした部分文字列を正規表現からどのように得ることができますか?

... 
$line = <FILE_IN>; 
until(($line =~m/$values_string/i && $line !~m/$rem_string/i) || eof) 
{ 
    if($line =~m/ \S{2}DT\S{3}/i) 
    { 

    # here I wish to get (only) substring that match to pattern \S{2}DT\S{3} 
    # (7 letter table name) and display it. 
     $line =~/\S{2}DT\S{3}/i; 
     print $line."\n"; 
... 

結果の印刷では、行全体が表示され、部分文字列は表示されません。私は別のアプローチを試みましたが、私はPerlをほとんど使用せず、おそらく基本概念の誤りを作ります。 (tablenameの行の位置は固定されていません。別の問題は[... SELECT * FROM AADTTAB、BBDTTAB、...])です。その部分文字列を取得するにはどうすればよいですか?

+0

すばやくさまざまなアプローチに感謝します。私はそれらを昨日と今日の朝に使用しようとしました。また、私の即興スタイルを教えてくれたことに感謝します。今日私は私がウィンドウズの下で働いていることを知らせなかったことを認識しています(私の真珠はこれです:これはperlです、v5.8.7はMSWin32-x86-マルチスレッド用に作られました)Copyright 1987-2005、Larry Wall Binary build 813 [148120] ActiveState www.ActiveState.com 2005年6月6日13時36分37秒)。 もう一度ありがとうございます。 –

+3

私は "無知は至福です"の後、少し苛立っていましたが、それは私に押しつけられました...まあ...今、私は「捕獲集団」が「括弧/括弧」という意味を知っています。私はすでに愚かな気がします。 ところで、パールの名前を変更するプロの世界的な投票は誰か - 私は知らない - パール? ;) –

+0

Larry Wallが名前を探していたときに、既にPearlという名前の言語がありました。 –

答えて

8

FROMに従うとパターンが一致する方が良いでしょう。テーブル名はASCII文字のみで構成されていると仮定します。その場合、あなたが望むものを言うのが最善です。これらの2つの注意点を除いて、リストコンテキストでの正規表現の一致が成功した場合、一致した部分文字列が返されることに注意してください。

#!/usr/bin/perl 

use strict; 
use warnings; 

my $s = 'select * from aadttab, bbdttab'; 
if (my ($table) = $s =~ /FROM ([A-Z]{2}DT[A-Z]{3})/i) { 
    print $table, "\n"; 
} 
__END__ 

出力:お使いのシステム上のperlのバージョンに応じ

C:\Temp> s 
aadttab 

、あなたが読むために全部が容易になるかもしれないという名前のキャプチャグループを使用することができる場合があります

if ($s =~ /FROM (?<table>[A-Z]{2}DT[A-Z]{3})/i) { 
    print $+{table}, "\n"; 
} 

perldoc perlreを参照してください。

20

括弧でグループ化し、最初のグループを格納します。

if($line =~ /(\S{2}DT\S{3})/i) 
{ 
    my $substring = $1; 
} 

上記のコードは、最初のテーブル名を引き出す直前の問題を修正しています。しかし、この質問では、すべてのテーブル名を引き出す方法も尋ねました。だから、:

# FROM\s+  match FROM followed by one or more spaces 
# (.+?)  match (non-greedy) and capture any character until... 
# (?:x|y)  match x OR y - next 2 matches 
# [^,]\s+[^,] match non-comma, 1 or more spaces, and non-comma 
# \s*;  match 0 or more spaces followed by a semi colon 
if($line =~ /FROM\s+(.+?)(?:[^,]\s+[^,]|\s*;)/i) 
{ 
    # $1 will be table1, table2, table3 
    my @tables = split(/\s*,\s*/, $1); 
    # delim is a space/comma 
    foreach(@tables) 
    { 
    # $_ = table name 
    print $_ . "\n"; 
    } 
} 

結果:

$ラインは= "SELECT * AADTTAB、BBDTTAB FROM;" 場合

出力:

AADTTAB 
BBDTTAB 

$ラインは= "AADTTAB SELECT * FROM;" 場合

出力:

AADTTAB 

Perlのバージョン:MSWIN32-のx86マルチスレッド

3

のために構築されv5.10.0がキャプチャグループを使用します。

$line =~ /(\S{2}DT\S{3})/i; 
my $substr = $1; 
+2

マッチ変数を使用する前に常にマッチが成功したかどうかを確認してください。 –

7

括弧を使用して、一部をつかむようになります$ 1、$ 2、$ 3の正規表現に変換することができます。 So:

$line = ' abc andtabl 1234'; 
if($line =~m/ (\S{2}DT\S{3})/i) { 
    # here I wish to get (only) substring that match to pattern \S{2}DT\S{3}  
    # (7 letter table name) and display it.  
    print $1."\n"; 
} 
-1

$&には、最後のパターンマッチでマッチした文字列が含まれています。

例:

$str = "abcdefghijkl"; 
$str =~ m/cdefg/; 
print $&; 
# Output: "cdefg" 

だからあなたは

if($line =~m/ \S{2}DT\S{3}/i) { 
    print $&."\n"; 
} 

警告のような何かができる:

あなたはそれがすべてのパターンが一致遅くなりますあなたのコードで$&を使用する場合

+1

$&とそれに関連する$ 'と$ 'を使わないようにすると、コード内のすべての正規表現に対してパフォーマンスが低下します。詳細は、perlre(http://perldoc.perl.org/perlre.html)を参照してください。 – daotoad

+1

'$&'の単なる言及は、あなたのコードのどこにあっても、すべての正規表現を減速させます。実際に値を使用するかどうかは関係ありません。 –

+0

ダーリン研究私は以前、そのような陳述を評価する習慣を持っていました。誰かがこの($&)悪い習慣がどれほど悪いかチェックしますか?最大10%/ 30%で結果を共有できますか? –

14

私はこれを好む:

my ($table_name) = $line =~ m/(\S{2}DT\S{3})/i; 

この

  1. スキャン$lineと "リスト" にパターンに
  2. 戻り、 "すべて" のキャプチャ(1)に対応するテキストをキャプチャします反対側に。

この擬似リストコンテキストは、リスト内の最初のアイテムを捕捉する方法です。これは、サブルーチンに渡されるパラメータと同じ方法で行われます。

my ($first, $second, @rest) = @_; 


my ($first_capture, $second_capture, @others) = $feldman =~ /$some_pattern/; 

注::あなたの正規表現は、状況の一握り以上に有用であることが文章についてはあまり想定している、と述べました。 7のうち3位と4位のようにdtを持たないテーブル名を取り込みませんか? 1)クイックアンドダーティー、2)あなたが適用範囲が限定されていれば十分です。

+0

本当にリストのコンテキストです、それについて何も疑問はありません!トリッキーなことは、1つのアイテムのリストを使用することです。 1つの項目リストで操作の結果をキャプチャすることは、呼び出し元の演算子またはサブルーチンからリストコンテキストの動作を強制したい場合に非常に便利です。 'my $ foo = @bar;'は 'my($ foo)= @bar;'と非常に異なっており、その区別は非常に便利です。 – daotoad

+0

ああ、便利です。私はいつも使っています。私は "偽"はそれを置くために悪い方法だと思います。私は、1つのリストがまだリストであることを知っています、それはちょうどスカラーのようにひどく見えます - それは私がとにかく取得しようとしているすべてです。 – Axeman

関連する問題