1. 最も単純なものから始める
「1-apple」という文字列があります。「1-apple」は
1 と apple を解析する必要があります。対応する正規表現は非常に単純です。^(\d)-(.+)$
その中で、
^
これは文字列の先頭を意味し、括弧で囲まれた内容は「グループ」を意味します。 :(\d)
は、数値のグループを意味し、(.+)
それが任意の値のグループであることを示し、$
文字列の終わりを示します。
対応するコード:
const str = "1-apple"
const regexp = /^(\d)-(.+)$/
let match = regexp.exec(str)
console.log(match[0])
console.log(match[1])
console.log(match[2])
括弧は 2 つしかありませんが、通常の戻り値が 3 つあることに注意してください。
match[0] = 1-リンゴ
match[1] = 1
match[2] = リンゴ
match[0] は、値が str 自体である完全一致を返します。本当に解析したいのは match[1] と match[2] であるため、この例では match[0] は明らかに役に立ちません。
2. リピートパターンのグループ化
文字列内に繰り返されるパターン (パターン) がある場合、次のような状況です。
1-apple
2-orange
3-pear
上記 3 行のテキストは、内容は異なりますが、法則は同じです。行: ( 数字
)-( 任意值
)
であるため、正規表現を使用してこれらの 3 行のテキストを照合できます。gm
識別子は後で追加する必要があることに注意してください (g はグローバルを表し、m は複数行を表します)。コードは次のとおりです。以下に続きます:
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm //注意:和上例相比,唯一的区别是后面加了gm标志
let match = regexp.exec(str)
console.log(match[0])
console.log(match[1])
console.log(match[2])
操作結果:
match[0] = 1-リンゴ
match[1] = 1
match[2] = リンゴ
1-appleのみが解析されるので、 2-orangeと3-pearを解析するにはどうすればよいでしょうか?
コードを少し変更してみましょう。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
let match
match = regexp.exec(str) // 第1次触发
console.log(match[0])
console.log(match[1])
console.log(match[2])
match = regexp.exec(str) // 第2次触发
console.log(match[0])
console.log(match[1])
console.log(match[2])
match = regexp.exec(str) // 第3次触发
console.log(match[0])
console.log(match[1])
console.log(match[2])
操作結果:
リンゴ1個リンゴ
1個
2-オレンジ
2
オレンジ
3 梨
3
梨
match = regexp.exec(str)
この例では、このステートメント行を 3 回続けてトリガーしています。
実際、ステートメントはまったく同じですが、各一致の戻り値は異なります。識別子を使用するとgm
、.exec メソッドは現在一致する値の最初の文字位置をインデックス変数に保存します (注:gm
識別子のないそのような変数は存在しません)。次回 .exec がトリガーされるとき、インデックスは開始されません。 from 0 検索の代わりに、最初の一致が完了した後の位置から 2 番目の一致が実行され、文字全体が一致するまで同様に実行されます。
.exec メソッドがこの小さな秘密を繰り返し実行できることがわかっているので、コードを再度変更するのは非常に簡単です。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm //注意:和上例相比,唯一的区别是后面加了gm标志
let match
while ((match = regexp.exec(str)) !== null) {
console.log('index = ', match.index)
console.log('result = ', match[0], match[1], match[2])
}
操作結果:
インデックス = 0
結果 = 1-リンゴ 1 リンゴ
インデックス = 8
結果 = 2-オレンジ 2 オレンジ
インデックス = 17
結果 = 3-ナシ 3 ナシ
あるいは、便宜上、結果を 2 次元配列にプッシュすることもできます。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
let match
let matches = []
while ((match = regexp.exec(str)) !== null) {
matches.push(match)
}
console.log(matches[0][1]) // 显示:1
console.log(matches[0][2]) // 显示:apple
console.log(matches[1][1]) // 显示:2
console.log(matches[1][2]) // 显示:orange
console.log(matches[2][1]) // 显示:3
console.log(matches[2][2]) // 显示:pear
3. matchAll デビュー
while ループが気に入らない場合は、matchAll を使用することもできるので、while ループと exec を使用する必要はありません。matchAll を使用するとイテレータの戻り値が取得されますが、for...of、配列スプレッド、または Array.from() を使用して関数を実現するとより便利です。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
const matches = str.matchAll(regexp) // 采用matchAll进行匹配
for (const match of matches) {
// 采用 for of 方式读取
console.log('index = ', match.index)
console.log('result = ', match[0], match[1], match[2])
}
このコードは、前の例とまったく同じ効果があります。
あるいは、Array.from() を使用して同じ効果を達成することもできます。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
const matches = str.matchAll(regexp)
Array.from(matches, (match) => {
// 采用 Array.from方式读取
console.log('index = ', match.index)
console.log('result = ', match[0], match[1], match[2])
})
または、より単純な ES6 の「3 つのドット」構文 (配列スプレッド):
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
const matches = [...str.matchAll(regexp)] // 采用 ... 方式展开str.matchAll(regexp)
// 遍历数组
for (let i = 0; i < matches.length; i++) {
console.log('index = ', matches[i].index)
console.log('result = ', matches[i][0], matches[i][1], matches[i][2])
}
この 3 つの点は「配列スプレッド」または「拡張構文」と呼ばれ、機能が多く複雑です。拡張構文がない場合、既存の配列要素を新しい要素に変換するには、push、splice、concat などのメソッドを組み合わせて使用するしかありません。配列の一部。拡張構文を使用すると、次のようなリテラル メソッドを通じて新しい配列の構築がより簡単かつ洗練されます。
const str = "1-apple\n2-orange\n3-pear"
const regexp = /^(\d)-(.+)$/gm
const matches = [...str.matchAll(regexp)] // 采用 ... 方式展开str.matchAll(regexp)
console.log(matches[0][1]) // 显示:1
console.log(matches[0][2]) // 显示:apple
console.log(matches[1][1]) // 显示:2
console.log(matches[1][2]) // 显示:orange
console.log(matches[2][1]) // 显示:3
console.log(matches[2][2]) // 显示:pear
3 つのドット「...」をstr.matchAll(regexp)
展開した後、追加のプッシュ操作を行わずに直接 2 次元配列を取得します。これは、以前に紹介した方法よりも簡単で直感的です。
4. 追記
この記事では、通常のグループ化に関する非常に単純な基本的なケースのみをリストします。さらに詳しい調査については、次の情報を参照してください。
【matchAll()详解】:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll
[配列スプレッド構文の詳細説明]:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax