どうやってそこに行きましたか?

どうやってそこに行きましたか?

次のようなファイルがあるとしましょう。

1,2,3-5,6
1,2,3-5,6,
1
1-3
1,2,3-,4,5-7
1,2,3-,4,5-7,
1,2,-3,4,5
1,2,-,3,4
1,2,,,3,4
,1,2,3

次の規則の組み合わせのみが有効と見なされます。

  1. 範囲 [0-9]+-[0-9]+
  2. グループ[0-9]+,[0-9]+
  3. 注文番号[0-9]+

カンマで終わる行も有効と見なす必要があります。

ただ抽出したいのですが

1,2,3-5,6
1,2,3-5,6,
1
1-3

以下に示す他の行はルールに準拠していないため

1,2,3-,4,5-7
1,2,3-,4,5-7,
1,2,-3,4,5
1,2,-,3,4
1,2,,,3,4
,1,2,3

これは、一部の行の範囲が不完全であり、一部の行のグループに数字が欠落しているためです。


PS:PCRE互換性のあるgrepソリューションをお勧めしますが、他のソリューションも大歓迎です。

ベストアンサー1

リストされた文字列(およびその文字列で始まる文字列)と,一致する完全なPCREは次のとおりです。

grep -P '^([0-9]+(-[0-9]+)?(,|$))+$'

どうやってそこに行きましたか?

一致の最も基本的な要素は数値です。[0-9]PCREのより単純な要素は、\d英語(ASCII)番号の正しい正規表現です。どのまたはそうでないかもしれません。一致することができるデバナガリ数字、例えば。その後、[0123456789]正確に書く必要があります。

それから連続した数字と一致します[0-9]+

数字(1、3、または26)の後にダッシュ「-」が続き、その後に1つ以上の数字(やはり数字)が続くことがあります。

[0-9]+(-[0-9]+)?

ここで、?ダッシュ番号の順序はオプションです。

その後、各数字:(3または数字の範囲4-9:)の後にはカンマ,(複数回)が続く必要があります。

([0-9]+(-[0-9]+)?,)+

最後のコンマが欠落している可能性があることを除いて:

([0-9]+(-[0-9]+)?(,|$))+

そして、必要に応じて前にカンマが表示されることがあります。

(^|,)([0-9]+(-[0-9]+)?(,|$))+

正規表現をテストテキストの始めと終わりに固定するのはとても良い考えです。

^((^|,)([0-9]+(-[0-9]+)?(,|$))+)$

テストして編集できます。このウェブサイトのPCRE正規表現

先行するカンマを拒否する必要がある場合は、次を使用してください。

^(([0-9]+(-[0-9]+)?(,|$))+)$

このため、正規表現マシンには代替解釈は不要です。すべて一致する必要があり、一致しない項目は拒否されます。

(GNU)拡張正規表現で書くことができます。

grep -E '^(([0-9]+(-[0-9]+)?(,|$))+)$'

基本正規表現(BRE):

grep '^\(\([0-9]\{1,\}\(-[0-9]\{1,\}\)\{0,1\},\{0,1\}\)\{1,\}\)$'

カンマがオプション,の場合、{0,1}正規表現エンジンは一致に対していくつかの決定を下すことができます。


説明的な正規表現?

(?x)スペースとコメントを含むより説明的な正規表現は、inで始まります。pcregrep

pcregrep '(?x)                  # tell the regex engine to allow
                                 # white space and comments.
           (?(DEFINE)            # subroutines that will be used. 
             (?<nrun> [0-9]+)    # run of digits (n-run).

              # define a range pair. A number run followed by
              # an optional ( dash and another number run )
             (?<range> (?&nrun)  (-(?&nrun))? )    # range pair.
             
             (?<sep> ,)          # separator used.
           )                     # end of definitions.

         # Actual regex to use:
         # (range) that ends in a (sep) 
         # or is at the end of the line,
         # several times (+).

         ^(  (?&range)  ((?&sep)|$)  )+$

        ' file

この正規表現(一度コンパイルされた場合)は元の正規表現とまったく同じで、すばやく実行されます。もちろん、正規表現をコンパイルするには(無視するのに十分な)追加時間がかかります。

テスト例はここ

おすすめ記事