文字列で正規表現のすべての項目を見つける方法

文字列で正規表現のすべての項目を見つける方法

POSIX awkとGawkでは、それぞれ文字列内の正規表現に一致するすべての項目をどのように見つけますか?

gsub具体的には、次の2つの目標のいずれかで、組み込み関数で置き換えられたすべての項目を見つけます。

  • ターゲット文字列内の各一致の位置と長さを探す

  • ターゲット文字列の部分文字列と一致する項目のみを探します。

最初の目標を達成するということは、2番目の目標を達成するという意味です。

  1. POSIX awkでは

    これらの目標の1つを達成する組み込み関数はありますか?

    組み込み関数は、match一番左と最長の一致のみを探しますか?

    match最初の目標を達成するには、各一致を探してターゲット文字列から一致と以前のプレフィックスを削除して、生成されたターゲット文字列のサフィックスを繰り返し適用するのが正しい方法ですか?はい https://gist.github.com/mllamazing/a40946fcf8211a503bed正しい実装?

  2. 石の腕では、

    array 2番目のターゲットのニーズに応じて、呼び出し後にpatsplit(string, array, fieldpat, seps) 一致が保存されますか?との間の区切り文字列に基づいてarray一致する位置の位置を見つけることは可能ですか?sepsseps[i]array[i]array[i+1]

ありがとうございます。

ベストアンサー1

  1. POSIX awkには、
    これらの目標の1つを達成する組み込み関数はありますか?

いいえ。単一の組み込み関数を使用せずに同じ効果を得ることができます。

組み込み関数は、match一番左と最長の一致のみを探しますか?

はい。 POSIX awk(およびGNU)awkの正規表現は常に貪欲です(つまり、最も長い一致が常に勝ちます)。

match最初の目標を達成するには、各一致を探してターゲット文字列から一致と以前のプレフィックスを削除して、生成されたターゲット文字列のサフィックスを繰り返し適用するのが正しい方法ですか?

はい、しかしgsub()100%の互換性が欲しいなら、詳細はかなり面倒です。

はいhttps://gist.github.com/mllamazing/a40946fcf8211a503bed正しい実装?

ほとんどの場合、削除するとユニバーサルサブライン。問題は詳細にあります。regex空の文字列の場合、コードが繰り返されます。 Classicではawk空の正規表現を受け入れませんが、IIRCではnawk受け入れます。この問題を解決するには、次の操作を行います。

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (str != "" && match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

しかし、100%互換性がないgsub()ため

$ echo 123 | awk '{ gsub("", "-") } 1'
-1-2-3-

上記の関数は3つの一致するもののみを探します(つまり、最後の一致を見逃します)。

次のことを試すことができます。

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        if (str == "") break
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

これは上記の問題を解決しますが、他の場合は中止されます。 ifstr = "123"とfunctionは最後に空の文字列を持つregex = "[1-9]*"2つの項目を検索しますが、whileは1つだけを探します。123gsub()123

今すぐ検索にはあまりにも怠惰な他の同様の違いがあるかもしれません。

  1. 石の腕では、

    array 2番目のターゲットのニーズに応じて、呼び出し後にpatsplit(string, array, fieldpat, seps) 一致が保存されますか?

ほとんどそうです。しかし、正規表現に関連する極端なケースは驚くほど微妙です。があるかもしれません一部上記のように違いがあります。

との間の区切り文字列に基づいてarray一致する位置の位置を見つけることは可能ですか?sepsseps[i]array[i]array[i+1]

はい。

おすすめ記事