logo BT编程语言
首页 动态 关于 更新记录
BT编程语言文档
BT编程语言(BT:Breezy Touch的缩写,语义为微风的轻抚,如此深的意境你可能感觉不到,让我们简单粗暴点,理解为B变T态,变态语言)一门极为简洁的编程语言,内核由Rust语言开发,BT的语法吸取了RustPHPJavaScript一些编程语言的优点,使语法更为简洁,学习更简单。 BT可以用来快速开发Web网站,因为她那独有的纯洁性,她不依赖ApacheNginx这些Web服务器,你只需要编写几行简单的BT代码,就可以配置好域名、SSL以及项目目录的绑定。 BT既属于编译型语言,又属于解释型语言,这也是BT独有的魔性,看你要做什么用了,但绝不像PHP只服务于Web,她可以开发桌面软件,如果做为BT脚本,那么她可以直接被运行,还可以嵌入常见的主流程序语言中被调用。
  • BT支持无限链式语法
  • BT不是强类型语言,所以编写程序时,更加自由
  • BT可以用来快速开发Web网站,只需要编写几行简单的BT代码,就可以配置好域名与项目目录的绑定。
  • BT可以开发桌面软件,BT脚本文件可以直接被运行,可以嵌入常见的主流程序语言中被调用。
  • BT语法超级自由,超级简洁,绝对称得上世界上最简洁的语法。
  • BT是跨平台的,可以运行在WindowsLinuxmacOS等多个操作系统上运行,‌而不需要对代码进行大量修改。‌

环境要求

适用于: Windows: Windows Windows Linux: Linux Linux macOS: macOS macOS

环境搭建

BT语言是所有编程语言中最简洁的语言,无需搭建环境,只需要拥有一个简单的记事本足以,然而为了更快乐的写代码,官方推荐: 代码编辑器:Vscode + 扩展(bt-lang) 在Vscode中直接打开bt-lang扩展 其它编辑器: HBuilderX + 扩展(bt-lang) 到HBuilderX插件市场进行安装 Sublime Text + 扩展(bt-lang) 到GitHub中下载,放入【软件安装目录\Data\Packages】即可

如何使用

BT语言编译器只能编译.bt文件,所以你的所有代码都应该写在以bt为后缀的文件中,BT语言编译器不仅是一个编译器,也是一个极为惊人的解释器。 当BT编译器打开时,如果当前目录存在main.bt文件时,会默认打开并执行里面的代码,不存在时,以终端命令行的方式运行。

运行调试

官网针对各种编辑器开发了针对BT语言的扩展,统一名称为bt-lang,这里以Vscode为示例,安装好bt-lang扩展后,打开项目(项目根目录中必须存在BT编译器),编辑或创建main.bt文件,代码: 然后点击Vscode侧边活动栏上的BT按钮,展开侧栏,点击运行,终端将输出脚本执行的内容。 项目完成后,下面是关于各个平台的简单使用方式:

1. Windows中使用

直接双击 bt.exe 程序即可,默认打开当前目录的main.bt文件,执行里面的代码。

2. Linux和macOS中使用

1)使用cd命令进入程序所在目录,然后赋予bt执行权限并运行,命令行: 2)Linux中,如果为web项目,可通过nohup命令执行,该命令用于在后台执行命令或程序,并且不受终端关闭的影响

BT语言教程

BT语言编译器打开时,默认先执行当前目录的main.bt文件,如果你需要做web端开发,那么该文件将作为项目配置文件,用于设定项目目录、SSL证书,以及web端的一些常用设置。 下载编译器后,进行解压,文件包中的main.bt文件中有详细的web配置注释。

代码示例

经典的开场白:

语法说明

BT的语法更贴近于JavaScript,有些地方与Rust相似,以下是BT的语法规范:
  • 单行语句结束时,尽量不要写分号;,在BT语言中,空格和换行属于结束语句。
  • 所有的语句都会拥有返回值,包括打印函数print,还有if for while loop
  • 声明变量时,无需使用let,直接声明即可,let主要用于声明当前作用域变量,而与全局变量分开。
注释,变量,常量,基本类型,函数,类,这几乎是每种编程语言都具有的编程概念。 为了能更好的学习BT编程语言,我们先从使用注释开始。

输出

BT中的数据输出函数主要为:printprintln print 用于输出内容,可输出任何类型的数据 printlnprint不同的是该函数无论打印任何数据,都会重新换行

使用注释

在编程中,注释是一种在代码中添加说明或备注的方式,这些说明或备注不会被计算机执行。注释的主要目的是为了提高代码的可读性和可维护性,帮助开发者(或未来的自己)理解代码的意图、逻辑或实现方式。 在BT语言中分两种注释,一种是单行注释,一种是多行注释。 单行注释使用两个斜杠//,多行注释使用两个斜杠和两个星号/**/,示例:

声明变量

变量:可以在程序执行过程中被重新赋值,即其值可以发生变化,也可重复赋值不同的数据类型
  • 变量命名规范为[a-zA-Z0-9_$],可为字母、数字、下划线和$混合
  • 变量命名不能以数字开头,不能以大写字母开头
  • 变量名称对大小写敏感(aBc 和 abc 是不同的变量)
没错,BT中声明变量就是这么简单,你无需像Java与C语言那样声明变量类型,也无需像JavaScript那样使用var和let前缀来声明。 在BT中,同一个变量可以重复赋值不同的数据类型,例如: 你也可以这么写,BT的魔性语法: 是不是很自由?

声明常量

常量:在定义后其值不可再被改变,用于表示程序中不会改变的数据,如配置参数、数学常数等。‌
  • 常量命名规范为[a-zA-Z0-9_$],可为字母、数字、下划线和$混合
  • 常量命名只能以大写字母开头
  • 常量名称对大小写敏感(ABC 和 ABc 是不同的常量)
在BT语言中,常量的首字母必须为大写字母,只要满足这个条件,定义的便是常量,如此简单,示例:

数据类型

BT语言中的基础数据类型:
  • Int 整数
  • Float 浮点
  • Bool 布尔
  • Str 字符
  • Array 数组
  • Object 对象
还有两个特殊值,Null和Empty,当转为bool值的时候,都为false。
  • null 表示不是有效的值,可被打印出来。
  • empty 表示空,它不是一个值,不属于任何类型,不会被打印出来。
除此之外还有一些其他数据类型:
  • Fn 函数
  • Class
  • File 文件对象
  • Date 时间对象
  • Break 循环阻断
  • Continue 循环跳过
  • Regex 正则表达式
我们通过变量来写一下这些数据类型: 上面的代码示例是按照标准JS语法编写的,为了展示BT的变态和魔性,来,请看下面的数组和对象的示例: 按照你那被调教的规规矩矩的代码编写方式,是没问题的,但BT的语法出奇的简洁,并不需要你这么规矩,无论是数组还是对象,元素之间并不需要用逗号分隔,你非要用,那是你个人的事。 你可能注意到了一个不可思议的存在,数组中的if,没错,必须支持if...elseif...else,如果你还不会用,请看下面的条件语句教学。

运算符

BT语言中的运算符非常丰富,主要包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符、逗号运算符等。 下面我将逐一介绍这些运算符及其用法:

算术运算符

+ 加法运算符 - 减法运算符 * 乘法运算符 / 除法运算符 % 取模运算符(求余数)

关系运算符

> 大于 < 小于 == 等于 != 不等于 >= 大于等于 <= 小于等于

逻辑运算符

&& 逻辑与 || 逻辑或 ! 逻辑非

位运算符

& 按位与,对两个数的二进制表示进行逐位比较,如果两个相应的位都为1,则该位的结果为1,否则为0 | 按位或,对两个数的二进制表示进行逐位比较,如果两个相应的位中至少有一个为1,则该位的结果为1,否则为0 ^ 按位异或,对两个数的二进制表示进行逐位比较,如果两个相应的位不同,则该位的结果为1,否则为0 ~ 按位取反,对一个数的二进制表示进行逐位取反,即0变为1,1变为0 << 左移,将一个数的各二进制位全部左移若干位,由符号位(最左边的位)的空位则以0来填充 >> 右移,将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

赋值运算符

= 简单赋值 += 加后赋值 -= 减后赋值 *= 乘后赋值 /= 除后赋值 %= 取模后赋值 <<= 左移后赋值 >>= 右移后赋值 &= 按位与后赋值 ^= 按位异或后赋值 |= 按位或后赋值

条件运算符

? : 条件运算符,格式为表达式1 ? 表达式2 : 表达式3。如果表达式1为真,则结果为表达式2的值,否则为表达式3的值。 说到二元运算,BT的魔性依然是性感的,示例:

逗号运算符

, 逗号运算符,用于顺序执行一系列运算,整个逗号表达式的值为最后一个表达式的值。

其他运算符

() 括号运算符,用于改变运算顺序或进行函数调用。 [] 下标运算符,用于访问数组元素。 . 成员运算符。 这些运算符是BT语言编程的基础,掌握它们对于编写高效、可读性强的代码至关重要。

条件语句

条件语句用于基于不同条件执行不同的逻辑。

bt 中,我们可使用以下条件语句:

  • if 语句 - 当条件为 true 时,执行该代码
  • if...else 语句 - 当if语句条件为 true 时执行代码,当条件为 false 时,执行else中代码
  • if...elseif...else 语句- 使用该语句来选择多个代码块之一来执行

if 语句

只有当指定条件为 true 时,该语句才会执行代码。

语法

注意:条件无需小括号,只有需要权重的时候,加入括号,这里是非必须的,为了保持整洁,简单条件语句无需加入括号

实例

当变量a大于10的时候,打印hello字符串:

if...else 语句

请使用 f...else 语句在条件为 true 时执行代码,在条件为 false 时执行其他代码。

语法

实例

当变量大于10的时候,打印hello字符串,其它结果则打印world字符串:

小插曲

其实在bt语言中,几乎所有的表达式都支持返回值,上面的打印代码可以简化为:

if...elseif...else 语句

使用 if...elseif...else 语句来选择多个代码块之一来执行。

语法

实例

当变量a大于10的时候,打印hello字符串,a大于15的时候,打印world字符串,其它结果则打印nice字符串:

以上就是关于条件语句的基本用法,少年,勇敢的去尝试吧,实践才是真理!

数字操作

基于Int和Float的操作支持以下函数:

len

返回数字的字符串长度

语法 Number.len()

to_fixed

将数字格式化为指定小数位数的字符串,四舍五入到最接近的值。

语法 Number.to_fixed(digits:Int)

digits:非必填,表示用于指定小数的位数

to_string

将数字转换为字符串,可以指定基数(进制)来转换不同进制下的字符串。

语法 Number.to_string(radix:Int)

radix:非必填,表示指定的进制基数

to_exponential

将数字格式化为指数表示的字符串,即科学计数法。

语法 Number.to_exponential()

字符串操作

基于字符串的操作支持以下函数:

len

返回字符串的长度

语法 Str.len()

char

根据索引返回字符串中的字符

语法 Str.char(index:Int)

index:必填,表示要返回字符的索引位置

char_code

根据索引返回字符串中字符的 Unicode 编码

语法 Str.char_code(index:Int)

index:必填,表示要返回字符的索引位置

concat

连接两个或多个字符串,并返回新的字符串

语法 Str.concat(...string:Str)

...string:必填,多参数

ends_with

检查字符串是否以指定的子字符串结尾,返回布尔值

语法 Str.ends_with(string:Str)

string:必填,用于查找的子字符串

contain

检查字符串是否包含指定的子字符串,返回布尔值

语法 Str.contain(string:Str)

string:必填,用于查找的字符串

index

返回在字符串中首次找到指定值的索引,如果不存在则返回 -1

语法 Str.index(string:Str)

string:必填,用于查找的字符串

last_index

返回在字符串中最后一次找到指定值的索引,如果不存在则返回 -1

语法 Str.last_index(string:Str)

string:必填,用于查找的字符串

repeat

返回一个新字符串,该字符串包含被连接在一起的指定数量的字符串副本

语法 Str.repeat(count:Int)

count:必填,表示重复的次数

replace

在字符串中查找匹配的子字符串,并替换为新的子字符串

语法 Str.replace(string:Str|regex:Regex, new_string:Str)

string|regex:必填,字符串或正则表达式,表示要替换的内容

new_string:必填,字符串类型,表示替换后的内容

search

使用正则表达式模式在字符串中查找匹配项,并返回第一个匹配项的索引

语法 Str.search(regex:Regex)

regex:必填,表示要匹配查找内容的正则表达式

match

使用正则表达式模式在字符串中查找匹配项,并返回包含结果的数组

语法 Str.match(regex:Regex)

regex:必填,表示要匹配查找内容的正则表达式

slice

提取字符串的片段,并在新的字符串中返回被提取的部分

语法 Str.slice(start:Int, end:Int)

start:必填,表示片段的起始位置

end:选填,表示片段的结束位置

split

通过将字符串分割为子字符串数组

语法 Str.split(string:Str)

string:必填,表示用于分割的字符串

starts_with

检查字符串是否以指定的子字符串开始,返回布尔值

语法 Str.starts_with(string:Str)

string:必填,用于查找的字符串

substring

返回位于两个指定下标之间的字符串的子串

语法 Str.substring(start:Int, end:Int)

start:必填,表示起始位置

end:选填,表示结束位置

to_lowercase

将字符串转换为小写

语法 Str.to_lowercase()

to_uppercase

将字符串转换为大写

语法 Str.to_uppercase()

trim

去除字符串两端的空白字符(包括空格、制表符、换行符等)

语法 Str.trim()

to_string

返回字符串的字符串表示(对于字符串类型,此方法通常直接返回字符串本身)

语法 Str.to_string()

escape_html

将字符串中的特殊HTML字符转换为HTML实体(用于防止XSS攻击)

语法 Str.escape_html()

unescape_html

将字符串中的HTML实体转换回特殊HTML字符(用于显示HTML内容)

语法 Str.unescape_html()

parse

将字符串转为Array数组或Object对象

语法 Str.parse()

以上便是字符串的原型函数,由于链式语法的原因,只要满足字符串类型可以无限调用原型函数,如下:

Array数组操作

基于数组的操作支持以下函数:

len

返回数组的长度

语法 Array.len()

join

将数组的所有元素连接成一个字符串,元素之间用指定的分隔符隔开

语法 Array.join(separator:Str)

separator:非必填,表示用来分隔数组元素的字符串,默认为逗号

each

对数组的每个元素执行一次给定的函数

语法 Array.each(callback(value:Any,key:Int))

callback:接收两个参数,元素值和索引

pop

移除数组中的最后一个元素,并返回该元素

语法 Array.pop()

push

向数组的末尾添加一个或多个元素,并返回新数组的长度

语法 Array.push(element1:Any, element2:Any, ...)

shift

移除数组中的第一个元素,并返回该元素

语法 Array.shift()

unshift

向数组的开头添加一个或多个元素,并返回新数组的长度

语法 Array.unshift(element1:Any, element2:Any, ...)

sort

根据指定的比较函数对数组元素进行排序

语法 Array.sort(compareFunction)

compareFunction:非必填,用来定义排序顺序的函数

reverse

反转数组中元素的顺序

语法 Array.reverse()

slice

从数组中返回一个新数组,该数组从开始索引到结束索引(不包括结束索引)

语法 Array.slice(start:Int, end:Int)

start:必填,起始索引

end:非必填,结束索引,默认到数组的末尾

splice

通过移除或替换现有元素以及添加新元素来修改数组的内容,并返回被移除的元素

语法 Array.splice(start:Int, deleteCount:Int, item:Any, item:Any,...)

start:必填,开始修改的位置

deleteCount:非必填,要删除的元素数量

...item:非必填,需添加的新元素

concat

将一个或多个数组或值连接到数组,并返回一个新的数组

语法 Array.concat(array1:Any, array2:Any, ...)

contain

判断数组是否包含指定的值,如果包含返回true,否则返回false

语法 Array.contain(value:Any)

index

返回数组中第一个与指定值相等的元素的索引,如果没有找到,则返回-1

语法 Array.index(value:Any)

last_index

返回数组中最后一个与指定值相等的元素的索引,如果没有找到,则返回-1

语法 Array.last_index(value:Any)

find

返回数组中第一个满足测试函数的元素值

语法 Array.find(callback:Fn(value:Any, key:Int, current:Any))

callback:测试每个元素的函数,返回布尔值

find_index

返回数组中第一个满足测试函数的元素的索引

语法 Array.find_index(callback:Fn(value:Any, key:Int, current:Any))

find_last

返回数组中最后一个满足测试函数的元素值

语法 Array.find_last(callback:Fn(value:Any, key:Int, current:Any))

find_last_index

返回数组中最后一个满足测试函数的元素的索引

语法 Array.find_last_index(callback:Fn(value:Any, key:Int, current:Any))

every

测试数组的所有元素是否都通过了指定的测试函数

语法 Array.every(callback:Fn(value:Any, key:Int, current:Any))

some

测试数组中的至少一个元素是否通过了指定的测试函数

语法 Array.some(callback:Fn(value:Any, key:Int, current:Any))

filter

创建一个新数组,其包含通过指定测试函数的所有元素

语法 Array.filter(callback:Fn(value:Any, key:Int, current:Any))

map

创建一个新数组,其结果是对数组中每个元素应用一个函数的结果

语法 Array.map(callback:Fn(value:Any, key:Int, current:Any))

reduce

对数组中的每个元素执行一个归并操作,将其归并为单一输出值

语法 Array.reduce(callback:Fn(acc:Any, value:Any, key:Int), initialValue:Any)

initialValue(非必填):初始值

reduce_right

与reduce相同,但从右向左执行

语法 Array.reduce_right(callback:Fn(acc:Any, value:Any, key:Int), initialValue:Any)

fill

用一个固定值填充数组中从起始索引到终止索引的所有元素

语法 Array.fill(value:Any, start:Int, end:Int)

start:非必填,填充开始的索引,默认为0

end:非必填,填充结束的索引(不包括该索引),默认为数组长度

flat

创建一个新数组,其中包含所有子数组元素的元素

语法 Array.flat(depth:Int)

depth(非必填):指定递归深度,默认为1

flat_map

首先使用映射函数映射每个元素,然后将结果压平

语法 Array.flat_map(callback:Fn(value:Any, key:Int, current:Any))

keys

返回一个新的数组,其包含数组的所有索引

语法 Array.keys()

values

返回一个新的数组,其包含数组的所有值

语法 Array.values()

entries

返回一个新的数组,其中包含数组的所有索引和值的数组

语法 Array.entries()

fn函数

函数是编程语言中的一个重要概念,由事件驱动的或者当它被调用时执行的可重复使用的代码块 在BT中,所有的语句都具有返回值,fn函数同样也是,默认会返回函数中最后一条语句的数据,当然你也可以在任何地方使用return返回数据,此时它会中断return后面的所有语句执行。

函数中的参数支持设置默认参数,如下:

Regex正则表达式

Regex:是正则表达式(regular expression)的简写。 ‌‌正则表达式(Regular Expression)‌是一种强大的文本处理工具,用于匹配字符串中的特定模式。它由普通字符和特殊字符(称为元字符)组成,用于描述一种字符串匹配的模式。正则表达式可以检查一个字符串是否含有某种子串、将匹配的子串做替换或从某个字符串中取出符合某个条件的子串等。‌ 正则表达式在许多编程语言和文本编辑器中都有广泛应用,例如VsCode、SublimeText等工具,以及PHP、Perl、‌Java、‌JavaScript、‌C#等编程语言。它主要用于文本搜索、替换、模式匹配等操作,能够帮助程序员高效地处理和分析文本数据。 例如:一个简单的正则表达式^\d+$用于匹配一串数字,其中^表示字符串的开始,\d+表示一个或多个数字。

语法

正则表达式主要由两个斜杠组成,最后一个斜杠后面为修饰符,用于配置匹配模式,如下:

re = /pattern/modifiers

pattern(模式) 表达式的模式 modifiers(修饰符) 用于指定全局匹配、区分大小写的匹配和多行匹配

修饰符

修饰符用于执行区分大小写和全局匹配:
  • i 执行对大小写不敏感的匹配
  • g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
  • m 执行多行匹配
  • s 允许 . 匹配 \n

字符类

字符类允许你定义匹配一组字符的规则,支持以下几种模式:
  • [xyz] 匹配 x、y 或 z 中的任意一个字符(并集)
  • [^xyz] 匹配除 x、y 和 z 之外的任何字符(取反)
  • [0-9] 匹配 0 到 9 范围内的数字(区间匹配)
  • [a-z] 匹配 a 到 z 范围内的任何小写字母(区间匹配)
  • [A-Z] 匹配 A 到 Z 范围内的任何大写字母(区间匹配)
  • [A-z] 匹配 A 到 z 范围内的任何大写和小写字母(区间匹配)
  • [[:alpha:]] 匹配任意字母字符(ASCII 字符类,等价于 [A-Za-z])
  • [[:^alpha:]] 匹配任何非字母字符(取反的 ASCII 字符类,等价于 [^A-Za-z])
  • [x[^xyz]] 嵌套/分组字符类,匹配 x 和除 y 和 z 之外的任意字符
  • [a-y&&xyz] 交集操作,匹配 x 或 y(即 a-y 与 xyz 的交集)
  • [0-9&&[^4]] 使用交集和取反进行的减法操作,匹配 0-9 中除 4 之外的字符
  • [0-9--4] 直接减法操作,匹配 0-9 中除 4 之外的字符
  • [a-g~~b-h] 对称差操作,匹配 a 和 h(即 a-g 与 b-h 的对称差)
  • [\[\]] 在字符类中转义,匹配 [ 或 ]
  • [a&&b] 空字符类,匹配不到任何字符

元字符

元字符(Metacharacter)是拥有特殊含义的字符:
  • . 匹配任意字符,除了换行符(如果设置了 s 标志,. 也可以匹配换行符)
  • \d 匹配任意数字字符(等价于 Unicode 类 \p{Nd})
  • \D 匹配任意非数字字符
  • \s 匹配任意空白字符(包括空格、制表符等)
  • \S 匹配任意非空白字符
  • \w 匹配任意单词字符(包括字母、数字和下划线)
  • \W 匹配任意非单词字符
  • \* 匹配字面上的 *,适用于所有 ASCII 字符,除了 [0-9A-Za-z<>]
  • \a 响铃符(\x07)
  • \f 换页符(\x0C)
  • \t 水平制表符(tab 键)
  • \n 换行符
  • \r 回车符
  • \v 垂直制表符(\x0B)
  • \A 匹配输入的开头
  • \z 匹配输入的结尾
  • \b 单词边界断言
  • \B 非单词边界断言(即反向的单词边界)
  • \b{start}, \< 单词开始边界断言
  • \b{end}, \> 单词结束边界断言
  • \b{start-half} 单词开始边界的半边断言
  • \b{end-half} 单词结束边界的半边断言
  • \123 八进制字符代码,最多三位数(当启用时)
  • \x7F 十六进制字符代码(精确为两位)
  • \x{10FFFF} 任何对应于 Unicode 代码点的十六进制字符代码
  • \u007F 十六进制字符代码(精确为四位)
  • \u{7F} 任何对应于 Unicode 代码点的十六进制字符代码
  • \U0000007F 十六进制字符代码(精确为八位)
  • \U{7F} 任何对应于 Unicode 代码点的十六进制字符代码
  • \p{Letter} Unicode 字符类(例如,匹配任意字母字符)
  • \P{Letter} 反向的 Unicode 字符类(例如,匹配任何非字母字符)
  • \pX 匹配由一个字母标识的 Unicode 字符类,例如 \pL 匹配所有字母
  • \PX 匹配由一个字母标识的取反 Unicode 字符类,例如 \PL 匹配非字母字符

重复匹配

在BT的正则表达式中,可以使用以下语法来指定重复模式:
  • x* 匹配零次或多次 x(贪婪匹配)
  • x+ 匹配一次或多次 x(贪婪匹配)
  • x? 匹配零次或一次 x(贪婪匹配)
  • x*? 匹配零次或多次 x(非贪婪/懒惰匹配)
  • x+? 匹配一次或多次 x(非贪婪/懒惰匹配)
  • x?? 匹配零次或一次 x(非贪婪/懒惰匹配)
  • x{n,m} 匹配至少 n 次 x,且至多 m 次 x(贪婪匹配)
  • x{n,} 匹配至少 n 次 x(贪婪匹配)
  • x{n} 精确匹配 n 次 x
  • x{n,m}? 匹配至少 n 次 x,且至多 m 次 x(非贪婪/懒惰匹配)
  • x{n,}? 匹配至少 n 次 x(非贪婪/懒惰匹配)
  • x{n}? 精确匹配 n 次 x(非贪婪/懒惰匹配)

提示:在这里,贪婪匹配 意味着正则表达式会尽可能多地匹配,而 非贪婪/懒惰匹配 则会尽可能少地匹配

空匹配

以下是BT正则表达式中与空匹配相关的符号及其含义:
  • ^ 匹配输入的开头(或在多行模式下匹配行的开头)
  • $ 匹配输入的结尾(或在多行模式下匹配行的结尾)
  • \A 仅匹配输入的开头(即使启用了多行模式也只匹配整个文本的开头)
  • \z 仅匹配输入的结尾(即使启用了多行模式也只匹配整个文本的结尾)
  • \b 匹配 Unicode 单词边界(当一侧是单词字符 \w,另一侧是非单词字符 \W、\A 或 \z 时)
  • \B 匹配非 Unicode 单词边界
  • \b{start}, \< 匹配 Unicode 单词开头边界(左侧为 \W 或 \A,右侧为 \w)
  • \b{end}, \> 匹配 Unicode 单词结尾边界(左侧为 \w,右侧为 \W 或 \z)
  • \b{start-half} 匹配半个 Unicode 单词开头边界(左侧为 \W 或 \A)
  • \b{end-half} 匹配半个 Unicode 单词结尾边界(右侧为 \W 或 \z)

提示:这些符号常用于匹配位置或边界,而不是实际字符

分组与标志

在BT正则表达式中,可以使用以下语法来进行分组:
  • (exp) 编号捕获组,捕获的内容会根据左括号的顺序进行编号(从 1 开始)。
  • (?Pexp)(?exp) 命名捕获组,同时也会被编号。组名必须是字母数字(a-z, A-Z, 0-9)。
  • (?:exp) 非捕获组,这种组只进行匹配但不会捕获结果。
  • (?flags) 在当前分组中设置标志(影响该分组内的匹配方式)。
  • (?flags:exp) 为特定的表达式 exp 设置标志,且该表达式为非捕获组。

ASCII 字符类

以下是基于 UTS#18 提供定义的 ASCII 字符类及其含义:
  • [[:alnum:]] 字母数字字符(即 [0-9A-Za-z])。
  • [[:alpha:]] 字母字符(即 [A-Za-z])。
  • [[:ascii:]] ASCII 字符(即 [\x00-\x7F],包括从 0 到 127 的所有 ASCII 字符)。
  • [[:blank:]] 空白字符(即 [\t ],包括水平制表符和空格)。
  • [[:cntrl:]] 控制字符(即 [\x00-\x1F\x7F],包括不可打印的控制字符)。
  • [[:digit:]] 数字字符(即 [0-9])。
  • [[:graph:]] 可见的图形字符(即 [!-~],包括除空格外的所有可打印字符)。
  • [[:lower:]] 小写字母(即 [a-z])。
  • [[:print:]] 可打印字符(即 [ -~],包括空格和所有可见的图形字符)。
  • [[:punct:]] 标点符号(即 [!-/:-@\[-{-~]`,包括标点和符号)。
  • [[:space:]] 空白字符(即 [\t\n\v\f\r ],包括制表符、换行符、垂直制表符、换页符、回车符和空格)。
  • [[:upper:]] 大写字母(即 [A-Z])。
  • [[:word:]] 单词字符(即 [0-9A-Za-z_],包括字母、数字和下划线)。

Unicode支持

Unicode 对内存使用和搜索速度的影响

该正则表达式库默认启用了对 Unicode 的全面支持,在大多数情况下,支持Unicode所需的额外内存开销是可以忽略的,并且通常不会影响搜索速度,但在某些情况下可能会有影响。

关于内存使用:

Unicode 的影响主要体现在 Unicode 字符类的使用上。Unicode 字符类往往非常庞大。例如,默认的 \w 匹配大约 14 万个不同的代码点。这需要额外的内存,并可能使正则表达式的编译变慢。虽然偶尔使用 \w 影响不大,但如果你写了 \w{100},那么默认情况下将生成一个相当大的正则表达式。 例如,(?-u:\w) 的 ASCII 版本明显比 Unicode 版本小得多,所以如果你的需求可以通过 ASCII 满足,最好使用 ASCII 字符类。ASCII 版本的 \w 可以通过多种方式表示,以下都是等价的:
  • [0-9A-Za-z_]
  • (?-u:\w)
  • [[:word:]]
  • [\w&&\p{ascii}]

关于搜索速度:

即使使用大型 Unicode 字符类,搜索速度通常也能很好地处理 Unicode。不过,一些更快的内部正则表达式引擎无法处理支持 Unicode 的单词边界断言。因此,如果你不需要 Unicode 感知的单词边界断言,建议使用 (?-u:\b) 代替 \b,前者使用 ASCII 版本的单词字符定义。 总之,虽然启用 Unicode 支持通常不会显著影响内存和性能,但在某些情况下使用 ASCII 类可以减少开销并提升性能。 BT语言的正则完全实现了 Unicode 技术标准 #18(UTS#18)中规定的“基本 Unicode 支持”(第一级)。 字符类 \w、\d 和 \s 默认都是支持 Unicode 的。使用 (?-u:\w) (?-u:\d)(?-u:\s) 可获得仅支持 ASCII 的定义。 类似的 \b 和 \B 使用 Unicode 定义的“单词”字符。若要获得仅支持 ASCII 的单词边界,可使用(?-u:\b)(?-u:\B)。这同样适用于特殊的单词边界断言(即 \b{start}\b{end}\b{start-half}\b{end-half})。 在多行模式下,^ 和 $ 不支持 Unicode,也就是说,它们只识别 \n(假设未启用 CRLF 模式),而不会识别 Unicode 定义的其他行终止符形式。 大小写不敏感的搜索支持 Unicode 并使用简单的大小写折叠。 Unicode 的一般类别、脚本和许多布尔属性默认可通过 \p{property name} 语法使用。 在所有情况下,匹配的结果都使用字节偏移量报告,准确地说,是 UTF-8 编码单元的偏移量。这允许在常数时间内对文本进行索引和切片操作。 在BT中,默认情况下,正则匹配是 Unicode 感知的,这意味着它可能匹配的比你想象的要多。例如:\d 要仅匹配 ASCII 十进制数字,以下所有内容都是等效的:
  • [0-9]
  • (?-u:\d)
  • [[:digit:]]
  • [\d&&\p{ascii}]

循环遍历

在 BT 脚本语言中,循环是遍历数据结构和控制流程的重要工具,BT 提供了三种循环类型:for、while 和 loop,每种循环都有其特定的使用场景,它们都支持 continuebreak 控制语句,同时也可以使用标签来对嵌套循环进行更精细的控制。

For循环

在 BT 中,for 循环专门用于遍历数组或对象,主要通过for...in...形式。通过 for 循环,可以轻松地对数组或对象中的每一项进行操作。

数组的遍历

同时获取键和值,这里的k和v是一个变量,你可以随意自定义,这里使用了key和value的首字母,for与in关键字之间如果存在一个变量,则为数组或对象的value,如果存在两个变量,则第一个变量为key(索引),第二个变量为value(值)

对象的遍历

除了数组,for 循环也可以用来遍历对象:

跳过循环项:continue

continue 可以用于跳过某一轮循环:

中断循环:break

break 用于提前终止循环:

标签:精确控制嵌套循环

通过使用标签,你可以更灵活地控制嵌套循环的终止和跳过。例如,使用break acontinue b来控制外层和内层循环:

While 循环

while 循环会在指定条件为 true 时重复执行代码块。在 BT 中,while 循环同样支持 continue 和 break,并且可以使用标签来控制循环。

使用 continue 和 break

和 for 循环类似,while 循环可以使用 continue 跳过某一轮迭代,或使用 break 提前退出循环。

使用标签控制嵌套循环

while 循环也可以结合标签来控制多层循环:

Loop 循环

loop 是一个无限循环,除非显式地使用 break 来中断循环,否则它会无限执行下去。loop 循环也支持 continue 和标签。

使用 continue 和 break

你可以结合 continue 和 break 来控制循环的执行逻辑:

使用标签控制嵌套的 loop

和其他循环一样,loop 循环也支持标签,用来控制多层循环的终止和跳过:

总结

BT 脚本中的三种循环 (for、while 和 loop) 各有其独特的用法,但它们都支持 continue 和 break 进行流程控制,并且可以通过标签来管理嵌套循环的执行。熟练掌握这些循环结构,可以让你的 BT 脚本更加高效、灵活。

class类

每个类的定义都以关键字class开头,后面跟着类名,里面包含有类的属性与方法的定义。 BT中的类没有指定的构造函数,因为类中的任何方法都可以成为构造函数 类的属性和方法默认情况下为私有,设为公共需添加pub关键字

date日期

在BT语言中,date是一个内置的标准库,用于处理日期和时间。通过该库,你可以轻松地进行时间对象的创建、时间戳的获取、时间格式化的操作以及时间字符串的解析等。 以下是一个详细的教程,帮助你理解和使用date库。 from_str函数解析字符串时间时,只解析数字串,然后根据年来定位,先确定年的位置,然后遵循下面规则进行解析,不存在的时间以0处理。

file文件操作

在BT语言中file是一个内置的标准库,用于处理文件和文件夹。通过该库,你可以轻松地进行文件的读写、重命名、复制以及删除等操作。以下是一个详细的教程,帮助你理解和使用file库。

Web端函数变量

main.bt中如果WEB_SERVICE_OPEN = true启用后,会开启Web服务,此模式下,会额外支持一些专门针对Web开发的一些函数和变量,分别如下:

header

设置web表头 Content-Type默认为text/html; charset=utf-8,所以Web中无需设置

语法 header(header_info:Object)

header_info:必填,用于设置web的表头信息

status_code

设置web的状态码

语法 status_code(code:Int)

code:必填,用于设置web的状态码

redirect

重定向

语法 redirect(url:Str)

code:必填,用于设置web的状态码

url

获取网页的链接,不包含域名

get

获取网页的get参数,Object类型

post

获取网页form表单传递的post参数,Object类型

method

获取form表单类型,值:POSTGET

server

服务器信息,可以包含服务器的主机名或服务器软件的名称及其版本。例如,Apache服务器可能会返回类似 Apache/2.4.41 (Unix),表示使用的Web服务器和版本信息。这个信息通常出现在HTTP响应的 Server 头中。 服务器信息,包含以下字段:

version:

这是HTTP协议的版本。例如,HTTP/1.1 或 HTTP/2。它指示客户端与服务器之间使用的协议版本,以确定如何格式化请求和响应。

scheme:

这个字段表示使用的协议方案,通常是 http 或 https。它决定了传输层的安全性以及如何与服务器通信。

headers:

HTTP请求或响应中的头信息。它是一个键值对集合,用于传递关于请求或响应的元数据,比如 Content-Type(表示内容类型)、User-Agent(标识发起请求的客户端)、Authorization(用于身份验证)、Host(请求目标的主机名)等。

local_addr:

本地地址,指的是服务器监听的IP地址和端口号。它通常代表服务器端的IP地址,例如 127.0.0.1:80,用来识别服务器的网络接口。

remote_addr:

远程地址,指的是客户端的IP地址和端口号,即发起请求的设备的地址。例如 192.168.1.100:54321。这可以用于识别和追踪请求的来源。

常用函数

以下是BT语言中常用的函数:

include

引用文件代码,类似PHP的include函数,常用于引入库或引入类。 提示:include中的代码作用域取决于引入的位置

语法 include(file_path:Str)

file_path:必填,需引用的文件路径

demo.bt中的代码: main.bt中的代码:

bool

将数据类型转为Bool类型

语法 bool(data:Any)

data:必填,需转换的数据

get_type

获取数据的类型

语法 get_type(data:Any)

data:必填,需获取类型的数据