2016-11-08 6 views
3

これはなぜ機能しないのですか?否定的な先取りを試みている。検疫用ビンと検査用ビンを除き、私はビンから番号を引き出そうとしています。私が前にある^でコードを実行すると、括弧内のすべての数字に一致します。 ^を削除すると、何も一致しません。ネガティブルックアヘッドRegEx

また、 "or演算子|"否定的な先取りの中に?私は^(?! Quarantine_Bin | Inspection_Bin)を持っています

また、特に[^Quarantine_Bin]を否定しようとしましたが、まだ一致しています。

^(?!Quarantine_Bin)\([0-9]+\) 

データ

Quarantine(2),Other_Bin(2),Quarantine_Bin(2),Quarantine_Bin(2), 
    Quarantine_Bin(5),Inspection_Bin(3),Regular_Bin(5),other(2) 
+0

、唯一の '2'と '5'は、上記の文字列から抽出された取得する必要がありますか? https://regex101.com/r/UAlyEG/1? –

+4

しかし、正直なところ、私はこのような正規表現は提案せず、代わりに 'split /、//'を別々のテストとして値にマッチさせます。複雑な正規表現はプログラムのメンテナンスには向いていません。 – Sobrique

+0

@Sobrique各行は異なる数のビンを持つことができるので、スプリットが最善のルートだと思いますか? – nzaleski

答えて

4

あなたはとして負の後読みを使用する必要があります。

(?<!\b(Quarantine|Inspection)_Bin)\([0-9]+\) 

RegEx Demo

(?<!\b(Quarantine|Inspection)_Bin)Quarantine_BinまたはInspection_Binがある場合は、障害をアサート否定後読みですouの前にrマッチ。 \bは単語境界です。

5

これは、単語の境界を指定する\bを使用し、^アンカーはあなたがここでやりたいことはありません

use warnings; 
use feature 'say'; 

my @strings = (
    "Quarantine_Bin(5),Inspection_Bin(3),Regular_Bin(5),other(2)", 
    "Quarantine(2),Other_Bin(2),Quarantine_Bin(2),Quarantine_Bin(2)," 
); 

for (@strings) { 
    my @m = $_ =~ /(?<!\b(?:Quarantine|Inspection)_Bin)\(\d+\)/g; 
    say "@m"; 
} 

後読みです。

数値に括弧が含まれ、(5) (2)(2) (2)の行が返されます。

あなたはかなりの数字

/(?<! \b(?: Quarantine|Inspection)_Bin) \((\d+) \)/xg; 

または後読み内側開口の括弧を引く(それが消費されていない)とクローズ1

/(?<! \b(?: Quarantine|Inspection)_Bin \() \d+/xg; 
を除外周りparethesisをキャプチャ追加し、それらを省略したい場合

返品行5 2および2 2、括弧はありません。

/x修飾子を使用すると、スペースを読みやすくすることができます。文字列の先頭がQuarantine_Binが続くのではなく、\([0-9]\)が続いている場合

2

^(?!Quarantine_Bin)\([0-9]+\)チェック。それは決して真実ではありません。

[^Quarantine_Bin]BQaeinrtu_ない1文字に一致します。あなたが望むものではありません。フィルタリングなし


、あなたが

\b\w+\([0-9]+\) 

を持っていると思いますあなたは

\b(?!Quarantine_Bin\b)(?!Inspection_Bin\b)\w+\([0-9]+\) 

または

を使用できるように \bは、 Quarantine_Binまたは Inspection_Binが続いていないことを確認したいです
\b(?!(?:Quarantine|Inspection)_Bin\b)\w+\([0-9]+\) 

先読み内の\bは、Quarantine_Bin_Xが除外されることを防ぎます。


便利:[^CHAR]*CHARにあるよう

(?:(?!STRING).)*STRINGにあります。

1

コメントにありますので、私は実際の答えとしてそれを肉付けします。

私は一般的に先読み/背後正規表現を避けることを提案します。なぜなら、それは複雑で乱雑になる可能性があるからです。あなたのユースケースでは、おそらくちょうどsplitの行を配列にして、それぞれを個別に扱います。以下のような

何か:だから

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

while (<DATA>) { 
    chomp; 
    #split on comma; 
    #grep out Inspection_Bin and Quarantine_Bin 
    my @fields = grep { not m/(?:Quarantine|Inspection)_Bin/ } split /,/; 
    #iterate each field, and select out two different regex matches, e.g. 
    #word bit and number bit. 
    print m/^(\w+)/, "=>", m/\((\d+)\)/, "\n" for @fields; 
} 


__DATA__ 
Quarantine(2),Other_Bin(2),Quarantine_Bin(2),Quarantine_Bin(2),Quarantine_Bin(5),Inspection_Bin(3),Regular_Bin(5),other(2)