正規表現
jqは、PHP、TextMate、Sublime Textなどと同様に、Oniguruma正規表現ライブラリを使っています。そのため、ここではjq固有の点を中心に説明します。
Onigurumaは複数の正規表現の構文に対応しています。jqが使うのは"Perl NG"(名前付きグループを持つPerl)の構文であることを知っておく必要があります。
jqの正規表現フィルターは、次のいずれかの形式で使えるように定義されています。
STRING | FILTER(REGEX)
STRING | FILTER(REGEX; FLAGS)
STRING | FILTER([REGEX])
STRING | FILTER([REGEX, FLAGS])
ここで、各要素は次のようになります。
- STRING、REGEX、FLAGSはjqの文字列で、jqの文字列への式の埋込みが適用されます。
- REGEXは、式の埋込み後に、有効な正規表現である必要があります。
- FILTERは、後述する
test、match、captureのいずれかです。
REGEXはJSON文字列に評価される必要があるため、正規表現を構成するための一部の文字をエスケープしなければなりません。たとえば、空白文字を表す正規表現 \s は、"\\s" と書きます。
FLAGSは、対応するフラグを1つ以上含む文字列です。
g- 全体検索(最初だけでなく、すべての一致を見つける)i- 大文字と小文字を区別しない検索m- 複数行モード(.が改行にも一致する)n- 空の一致を無視するp- sとmの両方のモードを有効にするs- 単一行モード(^->\A、$->\Z)l- 可能な限り長い一致を見つけるx- 拡張正規表現形式(空白とコメントを無視する)
x フラグで空白に一致させるには、\s を使います。例:
jq -n '"a b" | test("a\\sb"; "x")'
一部のフラグは、REGEX内でも指定できることに注意してください。例:
jq -n '("test", "TEst", "teST", "TEST") | test("(?i)te(?-i)st")'
これは、true、true、false、false に評価されます。
test(val), test(regex; flags)
match と同様ですが、一致オブジェクトは返しません。正規表現が入力に一致するかどうかに応じて、true または false だけを返します。
実行例 1
コマンド
jq 'test("foo")'入力
"foo"出力 1
true実行例 2
コマンド
jq '.[] | test("a b c # spaces are ignored"; "ix")'入力
["xabcd", "ABC"]出力 1
true出力 2
truematch(val), match(regex; flags)
matchは、見つかった一致ごとにオブジェクトを出力します。一致には、次のフィールドがあります。
offset- 入力の先頭からのオフセット。UTF-8コードポイント単位length- 一致の長さ。UTF-8コードポイント単位string- 一致した文字列captures- キャプチャグループを表すオブジェクトの配列
キャプチャグループのオブジェクトには、次のフィールドがあります。
offset- 入力の先頭からのオフセット。UTF-8コードポイント単位length- このキャプチャグループの長さ。UTF-8コードポイント単位string- キャプチャされた文字列name- キャプチャグループの名前(名前なしの場合はnull)
何にも一致しなかったキャプチャグループは、オフセット-1を返します。
実行例 1
コマンド
jq 'match("(abc)+"; "g")'入力
"abc abc"出力 1
{"offset": 0, "length": 3, "string": "abc", "captures": [{"offset": 0, "length": 3, "string": "abc", "name": null}]}出力 2
{"offset": 4, "length": 3, "string": "abc", "captures": [{"offset": 4, "length": 3, "string": "abc", "name": null}]}実行例 2
コマンド
jq 'match("foo")'入力
"foo bar foo"出力 1
{"offset": 0, "length": 3, "string": "foo", "captures": []}実行例 3
コマンド
jq 'match(["foo", "ig"])'入力
"foo bar FOO"出力 1
{"offset": 0, "length": 3, "string": "foo", "captures": []}出力 2
{"offset": 8, "length": 3, "string": "FOO", "captures": []}実行例 4
コマンド
jq 'match("foo (?<bar123>bar)? foo"; "ig")'入力
"foo bar foo foo foo"出力 1
{"offset": 0, "length": 11, "string": "foo bar foo", "captures": [{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]}出力 2
{"offset": 12, "length": 8, "string": "foo foo", "captures": [{"offset": -1, "length": 0, "string": null, "name": "bar123"}]}実行例 5
コマンド
jq '[ match("."; "g")] | length'入力
"abc"出力 1
3capture(val), capture(regex; flags)
名前付きキャプチャをJSONオブジェクトにまとめます。各キャプチャの名前をキーとし、一致した文字列を対応する値とします。
実行例 1
コマンド
jq 'capture("(?<a>[a-z]+)-(?<n>[0-9]+)")'入力
"xyzzy-14"出力 1
{ "a": "xyzzy", "n": "14" }scan(regex), scan(regex; flags)
入力のうち、正規表現に一致する重なりのない部分文字列を、ストリームとして出力します。フラグが指定されていれば、それに従います。一致がなければ、ストリームは空です。各入力文字列のすべての一致をまとめて取得するには、[ expr ] という書き方を使います。たとえば、[ scan(regex) ] です。正規表現にキャプチャグループが含まれている場合、フィルターは配列のストリームを出力し、各配列にはキャプチャされた文字列が入ります。
実行例 1
コマンド
jq 'scan("c")'入力
"abcdefabc"出力 1
"c"出力 2
"c"実行例 2
コマンド
jq 'scan("(a+)(b+)")'入力
"abaabbaaabbb"出力 1
["a","b"]出力 2
["aa","bb"]出力 3
["aaa","bbb"]split(regex; flags)
入力文字列を、正規表現の各一致箇所で分割します。
後方互換性のため、引数を1つ指定して呼び出した split は、正規表現ではなく文字列で分割します。
実行例 1
コマンド
jq 'split(", *"; null)'入力
"ab,cd, ef"出力 1
["ab","cd","ef"]splits(regex), splits(regex; flags)
対応する split と同じ結果を、配列ではなくストリームとして提供します。
実行例 1
コマンド
jq 'splits(", *")'入力
"ab,cd, ef, gh"出力 1
"ab"出力 2
"cd"出力 3
"ef"出力 4
"gh"実行例 2
コマンド
jq 'splits(",? *"; "n")'入力
"ab,cd ef, gh"出力 1
"ab"出力 2
"cd"出力 3
"ef"出力 4
"gh"sub(regex; tostring), sub(regex; tostring; flags)
入力文字列内の正規表現の最初の一致を、式の埋込み後の tostring で置き換えて得られる文字列を出力します。tostring はjqの文字列、またはそのような文字列のストリームである必要があります。各文字列は、名前付きキャプチャへの参照を含められます。名前付きキャプチャは、実質的に、capture が構築するようなJSONオブジェクトとして tostring に渡されます。そのため、"x"という名前でキャプチャされた変数への参照は、"\(.x)" という形式になります。
実行例 1
コマンド
jq 'sub("[^a-z]*(?<x>[a-z]+)"; "Z\(.x)"; "g")'入力
"123abc456def"出力 1
"ZabcZdef"実行例 2
コマンド
jq '[sub("(?<a>.)"; "\(.a|ascii_upcase)", "\(.a|ascii_downcase)")]'入力
"aB"出力 1
["AB","aB"]gsub(regex; tostring), gsub(regex; tostring; flags)
gsub は sub と同様ですが、正規表現の重なりのないすべての一致を、式の埋込み後の tostring で置き換えます。2番目の引数がjq文字列のストリームであれば、gsub は対応するJSON文字列のストリームを生成します。
実行例 1
コマンド
jq 'gsub("(?<x>.)[^a]*"; "+\(.x)-")'入力
"Abcabc"出力 1
"+A-+a-"実行例 2
コマンド
jq '[gsub("p"; "a", "b")]'入力
"p"出力 1
["a","b"]