Tài liệu tham khảo về API Ngôn ngữ diễn đạt thông thường (CEL)

Tài liệu này đóng vai trò là tài liệu tham khảo API hợp nhất cho Ngôn ngữ biểu thức chung (CEL). Thư viện này liệt kê tất cả các macro, toán tử và hàm tiêu chuẩn, cho biết chữ ký, hành vi và trạng thái hỗ trợ của chúng trên các ngăn xếp CEL chính thức.

Để biết thêm thông tin chi tiết về hành vi và quy cách ngôn ngữ, hãy tham khảo Định nghĩa ngôn ngữ CEL.

Phiên bản xếp chồng

Tài liệu tham khảo này dựa trên các phiên bản sau của ngăn xếp CEL:

  • CEL Go: v0.29.2 (trở lên)
  • CEL C++: v0.15.0
  • CEL Java: v0.13.1
  • CEL Python: v0.1.3
  • CEL C: Bản thử nghiệm phát triển (chưa phát hành)

Bản sao trên GitHub

Các cách triển khai chính thức của CEL được phản chiếu trên GitHub trong tổ chức cel-expr:


1. Core Macros

Đây là các macro tích hợp được mở rộng tại thời gian biên dịch.

Macro Mô tả Go C++ Java Python C
has(container.field) Kiểm tra xem một trường có xuất hiện trong một thông báo hay một khoá trong một bản đồ hay không.

Chữ ký:
has(container.field) -> bool

Ví dụ:
has(request.auth.claims.email)
list.all(var, predicate) Kiểm thử xem tất cả các phần tử trong danh sách có đáp ứng một vị từ hay không.

Chữ ký:
list.all(var, predicate) -> bool

Ví dụ:
[1, 2, 3].all(x, x > 0) // true
¹
list.exists(var, predicate) Kiểm thử xem có ít nhất một phần tử trong danh sách đáp ứng một vị từ hay không.

Chữ ký:
list.exists(var, predicate) -> bool

Ví dụ:
[1, 2, 3].exists(x, x > 2) // true
¹
list.exists_one(var, predicate) Kiểm thử xem có đúng một phần tử trong danh sách đáp ứng một vị từ hay không.

Chữ ký:
list.exists_one(var, predicate) -> bool

Ví dụ:
[1, 2, 3].exists_one(x, x == 2) // true
¹
list.filter(var, predicate) Lọc các phần tử của một danh sách theo một vị từ.

Chữ ký:
list.filter(var, predicate) -> list

Ví dụ:
[1, 2, 3].filter(x, x > 1) // [2, 3]
¹
list.map(var, transform) Chuyển đổi từng phần tử của một danh sách bằng cách sử dụng một biểu thức.

Chữ ký:
list.map(var, transform) -> list

Ví dụ:
[1, 2, 3].map(x, x * 2) // [2, 4, 6]
¹
list.map(var, filter, transform) Biến đổi các phần tử của một danh sách thoả mãn một thuộc tính bộ lọc.

Chữ ký:
list.map(var, filter, transform) -> list

Ví dụ:
[1, 2, 3].map(x, x > 1, x * 2) // [4, 6]
¹

¹ Được hỗ trợ trong thời gian chạy C vì các macro được mở rộng thành các phần hiểu trong quá trình biên dịch bằng trình biên dịch lưu trữ.


2. Toán tử cốt lõi

Đơn vị tổ chức Mô tả Go C++ Java Python C
Số học (+, -, *, /, %) Các phép toán số học chuẩn. Phủ định (-x) và Đẳng thức (+x). Phép nối danh sách (list + list) được hỗ trợ trong Go, C++, Java và Python.

Chữ ký:
T + T -> T
T - T -> T
T * T -> T
T / T -> T
T % T -> T
-T -> T
+T -> T
list + list -> list

Ví dụ:
1 + 2 * 3 // 7
[1] + [2] // [1, 2]
²
So sánh (==, !=, <, <=, >, >=) So sánh tiêu chuẩn. Các phép so sánh số là không đồng nhất (ví dụ: 1 == 1.0).

Chữ ký:
T == T -> bool
T != T -> bool
T < T -> bool
T <= T -> bool
T > T -> bool
T >= T -> bool

Ví dụ:
x < 42.0
1 == 1.0 // true
Logic (!, &&, ||, ? :) NOT, AND, OR và Ternary Conditional (Có điều kiện bậc ba) theo logic. VÀ/HOẶC sử dụng phương thức đánh giá đoản mạch.

Chữ ký:
!bool -> bool
bool && bool -> bool
bool || bool -> bool
bool ? T : T -> T

Ví dụ:
x > 0 ? "positive" : "non-positive"
Lập chỉ mục ([]) Truy cập vào phần tử của một danh sách theo chỉ mục hoặc khoá tra cứu trong một tệp ánh xạ.

Chữ ký:
list[int] -> T
map[K] -> V

Ví dụ:
tags[0]
users['john']
Thành viên (in) Kiểm tra xem phần tử có nằm trong danh sách hay khoá có nằm trong bản đồ hay không.

Chữ ký:
T in list -> bool
K in map -> bool

Ví dụ:
'admin' in roles

² Phép nối danh sách (list + list) không được hỗ trợ trong thời gian chạy C, mặc dù các toán tử số học khác được hỗ trợ.


3. Các hàm cốt lõi

Hàm chung và hàm chuỗi

Chức năng Mô tả Go C++ Java Python C
size Trả về kích thước của một chuỗi (ký tự), byte, danh sách hoặc bản đồ.

Chữ ký:
size(T) -> int (trong đó Tstring, bytes, list hoặc map)<br /><br />**Examples:**<br />size("hello") // 5`
contains Trả về kết quả cho biết liệu chuỗi có chứa chuỗi con hay không.

Chữ ký:
string.contains(string) -> bool

Ví dụ:
"hello".contains("ell") // true
startsWith Trả về liệu chuỗi có bắt đầu bằng tiền tố hay không.

Chữ ký:
string.startsWith(string) -> bool

Ví dụ:
"hello".startsWith("he") // true
endsWith Trả về việc chuỗi có kết thúc bằng hậu tố hay không.

Chữ ký:
string.endsWith(string) -> bool

Ví dụ:
"hello".endsWith("lo") // true
matches Trả về liệu chuỗi có khớp với biểu thức chính quy RE2 hay không.

Chữ ký:
string.matches(string) -> bool

Ví dụ:
"123".matches(r"^\d+$") // true

Các hàm bộ chọn ngày và giờ

Các hàm này trích xuất các thành phần từ google.protobuf.Timestamp hoặc google.protobuf.Duration.

Chức năng Mô tả Go C++ Java Python C
getFullYear Trả về năm có 4 chữ số.

Chữ ký:
timestamp.getFullYear([tz]) -> int

Ví dụ:
timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026
getMonth Trả về tháng (0-11).

Chữ ký:
timestamp.getMonth([tz]) -> int

Ví dụ:
timestamp("2026-07-23T00:00:00Z").getMonth() // 6
getDayOfMonth Trả về ngày trong tháng (1-31).

Chữ ký:
timestamp.getDayOfMonth([tz]) -> int

Ví dụ:
timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23
getDayOfWeek Trả về ngày trong tuần (0 = Chủ Nhật).

Chữ ký:
timestamp.getDayOfWeek([tz]) -> int

Ví dụ:
timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4
getDayOfYear Trả về ngày trong năm (0-365).

Chữ ký:
timestamp.getDayOfYear([tz]) -> int

Ví dụ:
timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203
getHours Trả về giờ (0-23).

Chữ ký:
timestamp.getHours([tz]) -> int
duration.getHours() -> int

Ví dụ:
duration("1h30m").getHours() // 1
getMinutes Trả về số phút (0-59).

Chữ ký:
timestamp.getMinutes([tz]) -> int
duration.getMinutes() -> int

Ví dụ:
duration("1h30m").getMinutes() // 30
getSeconds Trả về số giây (0-59).

Chữ ký:
timestamp.getSeconds([tz]) -> int
duration.getSeconds() -> int

Ví dụ:
duration("1h30m45s").getSeconds() // 45
getMilliseconds Trả về số mili giây (0-999).

Chữ ký:
timestamp.getMilliseconds([tz]) -> int
duration.getMilliseconds() -> int

Ví dụ:
duration("1.5s").getMilliseconds() // 500

Chuyển đổi kiểu

Loại Mục tiêu Mô tả Go C++ Java Python C
bool Chuyển đổi thành giá trị boolean.

Chữ ký:
bool(bool) -> bool
bool(string) -> bool

Ví dụ:
bool("true") // true
bytes Chuyển đổi thành byte.

Chữ ký:
bytes(bytes) -> bytes
bytes(string) -> bytes

Ví dụ:
bytes("hello") // b"hello"
double Chuyển đổi thành số thực có độ chính xác gấp đôi.

Chữ ký:
double(double) -> double
double(int) -> double
double(uint) -> double
double(string) -> double

Ví dụ:
double(1) // 1.0
duration Chuyển đổi thành khoảng thời gian.

Chữ ký:
duration(duration) -> duration
duration(string) -> duration

Ví dụ:
duration("1.5s") // 1.5s duration
int Chuyển đổi thành số nguyên 64 bit có dấu.

Chữ ký:
int(int) -> int
int(uint) -> int
int(double) -> int (làm tròn về 0)
int(string) -> int
int(timestamp) -> int (số giây kể từ thời điểm bắt đầu tính thời gian)

Ví dụ:
int(1.5) // 1
string Chuyển đổi thành chuỗi.

Chữ ký:
string(T) -> string (hỗ trợ bool, int, uint, double, bytes, timestamp, duration)<br /><br />**Examples:**<br />string(1.5) // "1.5"`
timestamp Chuyển đổi thành dấu thời gian.

Chữ ký:
timestamp(timestamp) -> timestamp
timestamp(string) -> timestamp (RFC3339)

Ví dụ:
timestamp("2026-07-23T00:00:00Z")
uint Chuyển đổi thành số nguyên 64 bit chưa ký.

Chữ ký:
uint(uint) -> uint
uint(int) -> uint
uint(double) -> uint
uint(string) -> uint

Ví dụ:
uint(1) // 1u
dyn Truyền giá trị đến loại động để kiểm tra loại.

Chữ ký:
dyn(T) -> dyn

Ví dụ:
dyn([1, "two"])
type Trả về loại giá trị.

Chữ ký:
type(T) -> type

Ví dụ:
type(1) // int

4. Tiện ích (Thư viện)

Thư viện Bindings

Chức năng Mô tả Go C++ Java Python C
cel.bind Liên kết một biến cục bộ để tránh đánh giá trùng lặp.

Chữ ký:
cel.bind(varName, initExpr, resultExpr) -> T

Ví dụ:
cel.bind(x, a + b, x * x)
(phiên bản 0.15.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)

Cách bật

Thư viện bộ mã hoá

Chức năng Mô tả Go C++ Java Python C
base64.encode Mã hoá byte thành chuỗi base64.

Chữ ký:
base64.encode(bytes) -> string

Ví dụ:
base64.encode(b"hello") // "aGVsbG8="
(phiên bản 0.6.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
base64.decode Giải mã chuỗi base64 thành byte. Gây ra lỗi khi thông tin đầu vào không hợp lệ.

Chữ ký:
base64.decode(string) -> bytes

Ví dụ:
base64.decode("aGVsbG8=") // b"hello"
(phiên bản 0.6.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
json.encode Chuyển đổi một giá trị CEL thành chuỗi JSON.

Chữ ký:
json.encode(dyn) -> string

Ví dụ:
json.encode([1, 2]) // "[1,2]"
(phiên bản 0.29.0)

Cách bật

Thư viện toán học

Chức năng Mô tả Go C++ Java Python C
math.greatest Trả về giá trị lớn nhất trong các đối số số (hoặc danh sách các số).

Chữ ký:
math.greatest(arg, ...) -> T

Ví dụ:
math.greatest(1, 3, 2) // 3
(phiên bản 0.13.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
math.least Trả về giá trị nhỏ nhất trong các đối số số (hoặc danh sách các giá trị số).

Chữ ký:
math.least(arg, ...) -> T

Ví dụ:
math.least([1, 3, 2]) // 1
(phiên bản 0.13.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
math.abs Giá trị tuyệt đối.

Chữ ký:
math.abs(T) -> T (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.abs(-1) // 1`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.sqrt Căn bậc hai.

Chữ ký:
math.sqrt(T) -> double (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.sqrt(9) // 3.0`
(phiên bản 0.25.1) (phiên bản 0.12.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
math.bitAnd Phép toán AND theo bit.

Chữ ký:
math.bitAnd(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitAnd(5, 3) // 1`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.bitOr Đảo bit OR.

Chữ ký:
math.bitOr(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitOr(5, 3) // 7`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.bitXor XOR theo bit.

Chữ ký:
math.bitXor(T, T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitXor(5, 3) // 6`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.bitNot Phép toán NOT theo bit.

Chữ ký:
math.bitNot(T) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitNot(1) // -2`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.bitShiftLeft Dịch trái theo bit.

Chữ ký:
math.bitShiftLeft(T, int) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitShiftLeft(1, 2) // 4`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.bitShiftRight Dịch bit sang phải.

Chữ ký:
math.bitShiftRight(T, int) -> T (hỗ trợ int, uint)<br /><br />**Examples:**<br />math.bitShiftRight(4, 2) // 1`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.ceil Làm tròn lên.

Chữ ký:
math.ceil(double) -> double

Ví dụ:
math.ceil(1.2) // 2.0
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.floor Làm tròn xuống.

Chữ ký:
math.floor(double) -> double

Ví dụ:
math.floor(1.8) // 1.0
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.round Làm tròn đến số nguyên gần nhất.

Chữ ký:
math.round(double) -> double

Ví dụ:
math.round(1.5) // 2.0
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.trunc Làm tròn theo hướng cắt bớt (về 0).

Chữ ký:
math.trunc(double) -> double

Ví dụ:
math.trunc(-1.8) // -1.0
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.isInf Kiểm tra xem số thực có phải là vô cực dương hay vô cực âm hay không.

Chữ ký:
math.isInf(double) -> bool

Ví dụ:
math.isInf(1.0/0.0) // true
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.isNaN Kiểm tra xem số thực có phải là NaN hay không.

Chữ ký:
math.isNaN(double) -> bool

Ví dụ:
math.isNaN(0.0/0.0) // true
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.isFinite Kiểm tra xem số thực có hữu hạn hay không.

Chữ ký:
math.isFinite(double) -> bool

Ví dụ:
math.isFinite(1.2) // true
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
math.sign Trả về dấu của giá trị (-1, 0 hoặc 1).

Chữ ký:
math.sign(T) -> T (hỗ trợ int, uint, double)<br /><br />**Examples:**<br />math.sign(-42) // -1`
(phiên bản 0.21.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)

Cách bật

Thư viện Protos

Chức năng Mô tả Go C++ Java Python C
proto.getExt Nhận trường tiện ích proto2 hoặc giá trị mặc định nếu chưa đặt.

Chữ ký:
proto.getExt(msg, extName) -> T

Ví dụ:
proto.getExt(msg, google.api.expr.test.int32_ext)
(phiên bản 0.13.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
proto.hasExt Kiểm tra xem trường tiện ích proto2 có được đặt hay không.

Chữ ký:
proto.hasExt(msg, extName) -> bool

Ví dụ:
proto.hasExt(msg, google.api.expr.test.int32_ext)
(phiên bản 0.13.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)

Cách bật

  • Đi: Truyền ext.Protos() đến cel.NewEnv().
  • C++: Thêm ProtoExtCompilerLibrary() vào CompilerBuilder. (Thời gian chạy được xử lý tự động).
  • Java: Thêm CelExtensions.protos() vào CelCompilerCelRuntime trình tạo.
  • Python: Nhập cel_expr_python.ext.ext_proto và sử dụng ExtProto() trong cel.NewEnv(extensions=[...]).

Thư viện danh sách

Chức năng Mô tả Go C++ Java Python C
distinct Trả về các phần tử riêng biệt.

Chữ ký:
list.distinct() -> list

Ví dụ:
[1, 2, 2].distinct() // [1, 2]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
flatten Làm phẳng các danh sách lồng nhau.

Chữ ký:
list.flatten([depth]) -> list

Ví dụ:
[[1], [2, 3]].flatten() // [1, 2, 3]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.7.1) (phiên bản 0.1.1)
lists.range Trả về danh sách các số nguyên [0, ..., n-1].

Chữ ký:
lists.range(int) -> list(int)

Ví dụ:
lists.range(3) // [0, 1, 2]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
reverse Đảo ngược danh sách.

Chữ ký:
list.reverse() -> list

Ví dụ:
[1, 2].reverse() // [2, 1]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
slice Trả về danh sách con (bao gồm ngày bắt đầu, không bao gồm ngày kết thúc).

Chữ ký:
list.slice(start, end) -> list

Ví dụ:
[1, 2, 3].slice(1, 3) // [2, 3]
(phiên bản 0.17.0) (phiên bản 0.11.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
sort Sắp xếp danh sách các phần tử có thể so sánh.

Chữ ký:
list.sort() -> list

Ví dụ:
[3, 1, 2].sort() // [1, 2, 3]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
sortBy Sắp xếp danh sách theo khoá được đánh giá từ biểu thức.

Chữ ký:
list.sortBy(var, expr) -> list

Ví dụ:
[{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}]
(phiên bản 0.22.0) (phiên bản 0.11.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
first Trả về phần tử đầu tiên dưới dạng không bắt buộc. Yêu cầu tiện ích bổ sung không bắt buộc.

Chữ ký:
list.first() -> optional

Ví dụ:
[1, 2].first() // optional(1)
(phiên bản 0.23.0) (phiên bản 0.15.0) (phiên bản 0.11.0) (phiên bản 0.1.2)
last Trả về phần tử cuối cùng dưới dạng không bắt buộc. Yêu cầu tiện ích bổ sung không bắt buộc.

Chữ ký:
list.last() -> optional

Ví dụ:
[1, 2].last() // optional(2)
(phiên bản 0.23.0) (phiên bản 0.15.0) (phiên bản 0.11.0) (phiên bản 0.1.2)

Cách bật

Sets Library

Chức năng Mô tả Go C++ Java Python C
sets.contains Kiểm tra xem list1 có chứa tất cả các phần tử của list2 hay không.

Chữ ký:
sets.contains(list1, list2) -> bool

Ví dụ:
sets.contains([1, 2], [1]) // true
(phiên bản 0.15.0) (phiên bản 0.10.0) (phiên bản 0.6.0) (phiên bản 0.1.1)
sets.equivalent Kiểm tra xem các danh sách có tương đương với tập hợp hay không (chứa các phần tử duy nhất giống nhau).

Chữ ký:
sets.equivalent(list1, list2) -> bool

Ví dụ:
sets.equivalent([1, 2], [2, 1, 1]) // true
(phiên bản 0.15.0) (phiên bản 0.10.0) (phiên bản 0.6.0) (phiên bản 0.1.1)
sets.intersects Kiểm tra xem các danh sách có ít nhất một phần tử chung hay không.

Chữ ký:
sets.intersects(list1, list2) -> bool

Ví dụ:
sets.intersects([1, 2], [2, 3]) // true
(phiên bản 0.15.0) (phiên bản 0.10.0) (phiên bản 0.6.0) (phiên bản 0.1.1)

Cách bật

Thư viện chuỗi

Chức năng Mô tả Go C++ Java Python C
charAt Trả về ký tự tại chỉ mục.

Chữ ký:
string.charAt(int) -> string

Ví dụ:
"hello".charAt(1) // "e"
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
indexOf Trả về chỉ mục của lần xuất hiện đầu tiên của chuỗi con hoặc -1.

Chữ ký:
string.indexOf(substr, [start]) -> int

Ví dụ:
"hello".indexOf("l") // 2
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
lastIndexOf Trả về chỉ mục của lần xuất hiện cuối cùng của chuỗi con hoặc -1.

Chữ ký:
string.lastIndexOf(substr, [end]) -> int

Ví dụ:
"hello".lastIndexOf("l") // 3
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
join Nối các chuỗi.

Chữ ký:
list(string).join([separator]) -> string

Ví dụ:
["a", "b"].join("-") // "a-b"
(phiên bản 0.10.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
split Chia chuỗi theo dấu phân cách.

Chữ ký:
string.split(separator, [limit]) -> list(string)

Ví dụ:
"a-b".split("-") // ["a", "b"]
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
substring Trả về chuỗi con (bao gồm cả điểm bắt đầu, không bao gồm điểm kết thúc).

Chữ ký:
string.substring(start, [end]) -> string

Ví dụ:
"hello".substring(1, 3) // "el"
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
trim Cắt khoảng trắng Unicode.

Chữ ký:
string.trim() -> string

Ví dụ:
" hello ".trim() // "hello"
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
replace Thay thế các lần xuất hiện của old bằng new.

Chữ ký:
string.replace(old, new, [limit]) -> string

Ví dụ:
"hello".replace("l", "w") // "hewwo"
(phiên bản 0.4.0) (phiên bản 0.10.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
reverse Đảo ngược các điểm mã Unicode.

Chữ ký:
string.reverse() -> string

Ví dụ:
"abc".reverse() // "cba"
(phiên bản 0.18.0) (v0.14.0) (phiên bản 0.13.0) (phiên bản 0.1.1)
lowerAscii Chuyển đổi ký tự ASCII thành chữ thường.

Chữ ký:
string.lowerAscii() -> string

Ví dụ:
"Hello".lowerAscii() // "hello"
(phiên bản 0.6.0) (phiên bản 0.11.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
upperAscii Chuyển đổi các ký tự ASCII thành chữ hoa.

Chữ ký:
string.upperAscii() -> string

Ví dụ:
"Hello".upperAscii() // "HELLO"
(phiên bản 0.6.0) (phiên bản 0.11.0) (phiên bản 0.2.0) (phiên bản 0.1.1)
quote Thoát chuỗi để in an toàn.

Chữ ký:
strings.quote(string) -> string

Ví dụ:
strings.quote("a\tb") // "\"a\\tb\""
(v0.14.0) (v0.14.0) (phiên bản 0.13.0) (phiên bản 0.1.1)

Cách bật

Thư viện biểu thức chính quy

Chức năng Mô tả Go C++ Java Python C
regex.replace Thay thế các kết quả trùng khớp bằng chuỗi thay thế (hỗ trợ tham chiếu ngược).

Chữ ký:
regex.replace(target, pat, repl, [limit]) -> string

Ví dụ:
regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123"
(phiên bản 0.25.1) (phiên bản 0.13.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
regex.extract Trả về mẫu trùng khớp đầu tiên (phải có một nhóm chụp).

Chữ ký:
regex.extract(target, pat) -> optional(string)

Ví dụ:
regex.extract("a123b", r"(\d+)") // optional("123")
(phiên bản 0.25.1) (phiên bản 0.13.0) (phiên bản 0.10.1) (phiên bản 0.1.1)
regex.extractAll Trả về tất cả các kết quả trùng khớp của mẫu (phải có một nhóm thu thập).

Chữ ký:
regex.extractAll(target, pat) -> list(string)

Ví dụ:
regex.extractAll("a1b2", r"(\d+)") // ["1", "2"]
(phiên bản 0.25.1) (phiên bản 0.13.0) (phiên bản 0.10.1) (phiên bản 0.1.1)

Cách bật

Two-Variable Comprehensions (Hiểu biết về hai biến)

Macro Mô tả Go C++ Java Python C
all Rút ngắn AND logic trên khoá/chỉ mục và giá trị.

Chữ ký:
list.all(i, v, pred) -> bool
map.all(k, v, pred) -> bool

Ví dụ:
[1, 2].all(i, v, v > 0) // true
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
exists Logic OR ngắn mạch trên khoá/chỉ mục và giá trị.

Chữ ký:
list.exists(i, v, pred) -> bool
map.exists(k, v, pred) -> bool

Ví dụ:
[1, 2].exists(i, v, v == 2) // true
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
existsOne Kiểm tra xem có chính xác một cặp thoả mãn vị từ hay không.

Chữ ký:
list.existsOne(i, v, pred) -> bool
map.existsOne(k, v, pred) -> bool

Ví dụ:
[1, 2].existsOne(i, v, v == 2) // true
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
transformList Chuyển đổi/lọc danh sách/bản đồ thành danh sách.

Chữ ký:
list.transformList(i, v, [filter], transform) -> list
map.transformList(k, v, [filter], transform) -> list

Ví dụ:
[1, 2].transformList(i, v, v * 2) // [2, 4]
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
transformMap Chuyển đổi các giá trị của danh sách/bản đồ thành một bản đồ (các khoá vẫn cố định).

Chữ ký:
list.transformMap(i, v, [filter], transform) -> map
map.transformMap(k, v, [filter], transform) -> map

Ví dụ:
[1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4}
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)
transformMapEntry Biến thành một bản đồ.

Chữ ký:
list.transformMapEntry(i, v, [filter], transform_entry) -> map
map.transformMapEntry(k, v, [filter], transform_entry) -> map

Ví dụ:
[1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4}
(phiên bản 0.22.0) (v0.14.0) (phiên bản 0.11.0) (phiên bản 0.1.1)

Cách bật

Thư viện các loại gốc

Tính năng Mô tả Go C++ Java Python C
Cấu trúc gốc Đăng ký và khởi tạo các loại gốc của máy chủ lưu trữ (cấu trúc Go / Java POJO) trong CEL.

Ví dụ:
Account{id: 123} (Java POJO được khởi tạo trong CEL)
(phiên bản 0.13.0) (phiên bản 0.13.0)

Cách bật

  • Go: Truyền ext.NativeTypes(...) (cung cấp các loại phản chiếu) đến cel.NewEnv().
  • C++: Không được hỗ trợ.
  • Java: Thêm CelExtensions.nativeTypes() (cung cấp các lớp Java) vào trình tạo CelCompilerCelRuntime.
  • Python: Không được hỗ trợ.

Thư viện mạng

Thư viện Mạng cung cấp các hàm để phân tích cú pháp, xác thực và thao tác với địa chỉ IP và khối CIDR.

Chức năng Mô tả Go C++ Java Python C
ip Phân tích cú pháp một chuỗi thành địa chỉ IP hoặc trích xuất IP từ một CIDR.

Chữ ký:
ip(string) -> IP
CIDR.ip() -> IP

Ví dụ:
ip("192.168.0.1")
cidr("192.168.0.0/24").ip()
(phiên bản 0.29.0)
isIP Kiểm tra xem một chuỗi có phải là địa chỉ IP hợp lệ hay không.

Chữ ký:
isIP(string) -> bool

Ví dụ:
isIP("192.168.0.1") // true
(phiên bản 0.29.0)
ip.isCanonical Kiểm tra xem chuỗi địa chỉ IP có ở định dạng chuẩn hay không.

Chữ ký:
ip.isCanonical(string) -> bool

Ví dụ:
ip.isCanonical("192.168.0.1") // true
(phiên bản 0.29.0)
cidr Phân tích cú pháp một chuỗi thành khối CIDR.

Chữ ký:
cidr(string) -> CIDR

Ví dụ:
cidr("192.168.0.0/24")
(phiên bản 0.29.0)
isCIDR Kiểm tra xem một chuỗi có phải là khối CIDR hợp lệ hay không.

Chữ ký:
isCIDR(string) -> bool

Ví dụ:
isCIDR("192.168.0.0/24") // true
(phiên bản 0.29.0)
containsIP Kiểm tra xem một khối CIDR có chứa địa chỉ IP hay không.

Chữ ký:
CIDR.containsIP(IP) -> bool
CIDR.containsIP(string) -> bool

Ví dụ:
cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true
(phiên bản 0.29.0)
containsCIDR Kiểm tra xem một khối CIDR có chứa một khối CIDR khác hay không.

Chữ ký:
CIDR.containsCIDR(CIDR) -> bool
CIDR.containsCIDR(string) -> bool

Ví dụ:
cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true
(phiên bản 0.29.0)
family Trả về họ IP (4 cho IPv4, 6 cho IPv6).

Chữ ký:
IP.family() -> int

Ví dụ:
ip("192.168.0.1").family() // 4
(phiên bản 0.29.0)
isGlobalUnicast Kiểm tra xem IP có phải là địa chỉ truyền đơn toàn cầu hay không.

Chữ ký:
IP.isGlobalUnicast() -> bool

Ví dụ:
ip("192.168.0.1").isGlobalUnicast() // true
(phiên bản 0.29.0)
isLinkLocalMulticast Kiểm tra xem IP có phải là địa chỉ truyền tin đa hướng cục bộ hay không.

Chữ ký:
IP.isLinkLocalMulticast() -> bool

Ví dụ:
ip("224.0.0.1").isLinkLocalMulticast() // true
(phiên bản 0.29.0)
isLinkLocalUnicast Kiểm tra xem IP có phải là địa chỉ truyền đơn cục bộ liên kết hay không.

Chữ ký:
IP.isLinkLocalUnicast() -> bool

Ví dụ:
ip("169.254.0.1").isLinkLocalUnicast() // true
(phiên bản 0.29.0)
isLoopback Kiểm tra xem IP có phải là địa chỉ vòng lặp hay không.

Chữ ký:
IP.isLoopback() -> bool

Ví dụ:
ip("127.0.0.1").isLoopback() // true
(phiên bản 0.29.0)
isMask Kiểm tra xem CIDR có phải là mặt nạ mạng con hợp lệ hay không.

Chữ ký:
CIDR.isMask() -> bool

Ví dụ:
cidr("255.255.255.0/24").isMask() // true
(phiên bản 0.29.0)
isUnspecified Kiểm tra xem IP có phải là địa chỉ không xác định (ví dụ: 0.0.0.0) hay không.

Chữ ký:
IP.isUnspecified() -> bool

Ví dụ:
ip("0.0.0.0").isUnspecified() // true
(phiên bản 0.29.0)
masked Trả về khối CIDR được che.

Chữ ký:
CIDR.masked() -> CIDR

Ví dụ:
cidr("192.168.0.1/24").masked() // 192.168.0.0/24
(phiên bản 0.29.0)
prefixLength Trả về độ dài tiền tố của khối CIDR.

Chữ ký:
CIDR.prefixLength() -> int

Ví dụ:
cidr("192.168.0.0/24").prefixLength() // 24
(phiên bản 0.29.0)
string Chuyển đổi IP hoặc CIDR thành chuỗi.

Chữ ký:
string(IP) -> string
string(CIDR) -> string

Ví dụ:
string(ip("192.168.0.1")) // "192.168.0.1"
(phiên bản 0.29.0)

Cách bật

  • Đi: Truyền ext.Network() đến cel.NewEnv().
  • C++: Không được hỗ trợ.
  • Java: Không được hỗ trợ.
  • Python: Không được hỗ trợ.

5. Tính năng nâng cao

Tóm tắt về các tính năng nâng cao

Tính năng Mô tả Go C++ Java Python C
Đánh giá một phần Đánh giá bằng các đầu vào bị thiếu; trả về các giá trị không xác định hoặc một biểu thức đơn giản. ³
Đánh giá không đồng bộ Thực thi đồng thời các hàm mở rộng mà không bị chặn.
Trình xác thực AST Các quy trình kiểm tra phân tích tĩnh trên AST đã kiểm tra sau khi kiểm tra loại.
Trình tối ưu hoá AST Viết lại AST (gấp hằng số, nội tuyến, CSE) để cải thiện hiệu suất.
Trình biên dịch chính sách CEL Biên dịch các cấu trúc chính sách dựa trên YAML thành các AST CEL tiêu chuẩn.

³ Go hỗ trợ tạo AST còn lại (AST được cắt tỉa). ⁴ C++ và Java hỗ trợ trả về UnknownSet / CelUnknownSet trong thời gian chạy, nhưng không hiển thị các API công khai để tạo AST còn lại. ⁵ Go sử dụng AsyncBinding / AsyncOp trả về các kênh. ⁶ Java sử dụng CelAsyncRuntime trả về ListenableFuture.

Đánh giá một phần (Không xác định)

Việc đánh giá một phần cho phép đánh giá một biểu thức khi chỉ biết một tập hợp con của các biến đầu vào (đối số). Thay vì thất bại, quá trình đánh giá sẽ tạo ra một kết quả cho biết nội dung còn thiếu hoặc một biểu thức đơn giản.

  • Go: Hỗ trợ đầy đủ. Cho phép xác định PartialActivation bằng các mẫu thuộc tính không xác định. Quá trình đánh giá trả về giá trị types.Unknown. Go hỗ trợ tạo AST dư (Env.ResidualAst) là một AST đã được cắt tỉa, đơn giản hoá, chỉ chứa những phần của biểu thức không thể đánh giá.
  • C++: Hỗ trợ các giá trị Unknown. Các mẫu thuộc tính không xác định được định cấu hình thông qua Activation::set_unknown_attribute_patterns. Hàm Evaluation trả về một UnknownSet. API công khai hiện không hiển thị quá trình tạo AST còn lại.
  • Java: Hỗ trợ đánh giá một phần thông qua PartialVars được truyền đến Program.eval(). Quá trình đánh giá trả về một CelUnknownSet. API công khai hiện không hiển thị quá trình tạo AST còn lại.
  • Python / C: Không hỗ trợ gốc.

Đánh giá không đồng bộ

Hoạt động đánh giá không đồng bộ cho phép các biểu thức CEL gọi các hàm thực thi không đồng bộ (ví dụ: thực hiện các RPC hoặc truy vấn cơ sở dữ liệu) và chặn hoạt động đánh giá cho đến khi có kết quả mà không chặn luồng thực thi chính.

  • Go: Hỗ trợ các hàm không đồng bộ nạp chồng thông qua AsyncBindingAsyncOp. Các hàm không đồng bộ trả về một kênh Go (<-chan ref.Val) và trình thông dịch quản lý quá trình thực thi và đồng bộ hoá đồng thời.
  • Java: Hỗ trợ đánh giá không đồng bộ thông qua CelAsyncRuntimeAsyncProgram. Nó sử dụng ListenableFuture để biểu thị các giá trị đang chờ xử lý và tự động thúc đẩy quá trình đánh giá hoàn tất khi các giá trị trong tương lai được phân giải.
  • C++ / Python / C: Không có tính năng hỗ trợ tích hợp.

Trình xác thực AST

Trình xác thực thực hiện phân tích tĩnh trên AST đã kiểm tra sau khi kiểm tra loại để thực thi các ràng buộc dành riêng cho miền trước khi chương trình được thực thi.

  • Go: Hỗ trợ giao diện ASTValidator. Các trình xác thực chuẩn bao gồm cel.validator.duration, cel.validator.timestamp, cel.validator.matches (biểu thức chính quy), cel.validator.homogeneous_literalscel.validator.comprehension_nesting_limit.
  • C++: Hỗ trợ cel::Validator. Các xác thực chuẩn bao gồm AstDepthValidator, ComprehensionNestingLimitValidator, DurationLiteralValidator, HomogeneousLiteralValidator, MatchesValidatorTimestampLiteralValidator.
  • Java: Hỗ trợ CelValidatorCelAstValidator. Các trình xác thực chuẩn bao gồm AstDepthLimitValidator, ComprehensionNestingLimitValidator, DurationLiteralValidator, HomogeneousLiteralValidator, RegexLiteralValidatorTimestampLiteralValidator.
  • Python / C: Không hỗ trợ trực tiếp.

Trình tối ưu hoá AST

Các trình tối ưu hoá sẽ viết lại AST để cải thiện hiệu suất thực thi. Các trình tối ưu hoá thuộc một trong hai danh mục: trình tối ưu hoá tĩnh và trình tối ưu hoá thời gian chạy. C++, Java và Go hỗ trợ tối ưu hoá thời gian chạy. CEL Java và Go cũng hỗ trợ các trình tối ưu hoá tĩnh. Các hoạt động tối ưu hoá điển hình bao gồm việc gộp hằng số (đánh giá trước các biểu thức phụ bằng các đầu vào hằng số) và loại bỏ biểu thức phụ chung (CSE).

  • Go: Hỗ trợ việc thu gọn AST trong quá trình biên dịch/lập kế hoạch.
  • C++: Hỗ trợ việc giảm hằng số thông qua tiện ích cel::extensions::EnableConstantFolding tại thời điểm lập kế hoạch.
  • Java: Hỗ trợ giao diện CelOptimizer. Các trình tối ưu hoá chuẩn tắc bao gồm ConstantFoldingOptimizer (có thể gấp các nhánh đoản mạch bằng cách mô phỏng đánh giá một phần), InliningOptimizerSubexpressionOptimizer (CSE).
  • Python / C: Không hỗ trợ trực tiếp.

Trình biên dịch chính sách CEL

CEL Policy là một định dạng dựa trên YAML để kết hợp nhiều biểu thức CEL với các biến, khối so khớp, đầu ra có điều kiện và quy tắc lồng nhau. Nó được thiết kế cho các công cụ chính sách phức tạp (như Kubernetes Admission Control) trong đó các biểu thức CEL đơn lẻ sẽ trở nên khó đọc.

Trình biên dịch chính sách biên dịch các chính sách YAML này thành một AST CEL tiêu chuẩn duy nhất, nghĩa là chúng hoàn toàn tương thích với các thời gian chạy CEL tiêu chuẩn và kế thừa tất cả các đảm bảo về hiệu suất và độ an toàn.

  • Go: Được hỗ trợ thông qua third_party/cel/go/policy.
  • C++: Được hỗ trợ thông qua third_party/cel/cpp/policy.
  • Java: Được hỗ trợ thông qua third_party/java/cel/policy.
  • Python / C: Không được hỗ trợ trực tiếp.