Skip to main content

[str] 字符串工具库

Yak 的字符串我们在语言基础中,有一些简单的讲解,但是我们没有讲关于字符串的其他操作,在本节中,我们将会着重讲解 Yak 自带的字符串处理函数以及相关细节问题

Yak 中字符串有哪些形态?#

和 Golang 类似,在 Yak 中,我们的字符串支持如下定义

strValue := "this is a str"strValue2 := `this is a str blockmulti-linesand more...`
println("strValue: ", strValue)println("strValue2: ", strValue2)
/*OUTPUT:
strValue:  this is a strstrValue2:  this is a str blockmulti-linesand more...*/
与其他语言的不同

注意

  1. 单引号只能用于包裹 byte, 不能用于包裹字符串。
  2. 文本块的定义与 Python 也不同,单个反引号即可

字符串的基本操作#

值得注意的是

在 yak 中,str 是字符串包的包名,然而一般在 Golang 中,字符串操作使用 strings 作为包名

取子字符串#

与大多数语言都一样,yak 支持使用索引来取子字符串。

strValue := "abcdefghijk"subStr1 := strValue[2:6]subStr2 := strValue[:6]subStr3 := strValue[3:]// subStr4 := strValue[-3:]   # 这个暂时是不支持的,如果遇到这种情况,请使用 subStrsubStr4 := strValue[len(strValue)-3:]   # 这个暂时是不支持的,如果遇到这种情况,请使用 subStr4 := strValue[len(strValue)-3:]println("subStr1: ", subStr1)println("subStr2: ", subStr2)println("subStr3: ", subStr3)println("subStr4: ", subStr4)
/*OUTPUT:
subStr1:  cdefsubStr2:  abcdefsubStr3:  defghijksubStr4:  ijk*/

继承 Golang 的字符串处理包 strings#

我们看如下列表,即可知道 Yak 支持的 Golang 原生 strings 函数,对有 Golang 基础的同学来说,学习无压力,可以无缝转换

具体的文档,我们可以参考 Golang 官方文档,以下是 Yak 支持的基础字符串函数,具体函数的用法,我们可以在

strings 官方文档:https://golang.org/pkg/strings/

中找到如下函数的字符串操作内容

IndexAnyStartWithEndWithTitleJoinTrimLeftTrimPrefixTrimRightTrimSuffixTrimSplitSplitAfterSplitAfterNSplitNToLowerToUpperHasPrefixHasSuffixRepeatToTitleSpecialToTitleContainsReplaceAllReplaceNewReaderIndexCountCompareContainsAnyEqualFoldFieldsIndexByteLastIndexLastIndexAnyLastIndexByteToLowerSpecialToUpperSpecialToValidUTF8

yak 独门绝技#

基础字符串操作补充#

  1. 相当于 fmt.Sprintf 的快捷函数 fn str.f(var_1: string, vars: ...interface {}): string
  2. 判断字符串前缀 fn str.EndsWith(var_1: string, var_2: string): bool
  3. 判断字符串以指定字符开始 fn str.StartsWith(var_1: string, var_2: string): bool
  4. 把字符串全部小写,并去除左右空白 fn str.LowerAndTrimSpace(var_1: string): string
  5. Split之后把元素两边的空白移除 fn str.SplitAndTrim(var_1: string, var_2: string): []string
  6. 把 Json 字符串转换成 map[string]string fn str.JsonToMap(var_1: string): map[string]string
  7. 把 Json 字符串转换成 []map[string]string fn str.JsonToMapList(var_1: string): []map[string]string
  8. 使用 io.Reader 读取 Json 数据流 fn str.JsonStreamToMapList(var_1: io.Reader): []map[string]interface {}
  9. 把字符串数组作为 Path 进行拼接fn str.PathJoin(vars: ...string): string
  10. 正则匹配 fn str.RegexpMatch(var_1: interface {}, var_2: string): bool
  11. 把一个对象转变成 Json 字符串,做好锁进展示 fn str.ToJsonIndentStr(var_1: interface {}): string

字符串 Slice/ListMap/Dict 操作函数#

  1. 判断字符串是否包含指定的数组中的任何一个元素 fn str.StringContainsAnyOfSubString(var_1: string, var_2: []string): bool
  2. 判断 StringSlice 中是不是包含指定元素 fn str.StringSliceContains(var_1: []string, var_2: string): bool
  3. 判断 StringSlice 中是不是包含后续所有字符串fn str.StringSliceContainsAll(var_1: []string, vars: ...string): bool
  4. 移除 List/Slice 中重复的元素fn str.RemoveRepeat(var_1: []string): []string
  5. 从一个字典中取 key 对应的值,如果没有,设置为 idEmptyDefault 的默认值fn str.ParamsGetOr(var_1: map[string]string, key: string, ifEmptyDefault: string): string

渗透测试可能需要使用的函数#

  1. 判断一个密码是不是强密码 fn str.IsStrongPassword(var_1: string): bool
  2. 把域名和端口拼接成一个地址 fn str.HostPort(var_1: string, var_2: interface {}): string
  3. 让 IPv4 地址退化成一个 C 段地址 fn str.IPv4ToCClassNetwork(var_1: string): (string, error)
  4. 判断一个字符串是不是 IPv4 fn str.IsIPv4(var_1: string): bool
  5. 判断一个字符串是不是 IPv6 fn str.IsIPv6(var_1: string): bool
  6. 把字符串(URL/Addr)中的主机和端口解析出来 fn str.ParseStringToHostPort(var_1: string): (host string, port int, _ error)
  7. 把以,分割的字符串解析成主机信息,可解析内容为网段、IP、域名等 fn str.ParseStringToHosts(var_1: string): []string
  8. 把字符串按行来分割 fn str.ParseStringToLines(var_1: string): []string
  9. 把字符串(端口和端口的集合例如:22,3306,8080-8088)解析成单独端口 fn str.ParseStringToPorts(var_1: string): []int
  10. 把字符串(网络地址)转变成可能的标准格式的 Url fn str.ParseStringToUrls(vars: ...string): []string
  11. 把字符串(网络地址)转变成可能的标准格式的 Url(可能以 www 作为域名开头)fn str.ParseStringToUrlsWith3W(vars: ...string): []string
  12. 随机生成一个指定长度的随机字符串,可作为密码 fn str.RandSecret(var_1: int): string
  13. 随机生成一个指定长度字符串 fn str.RandStr(var_1: int): string

特殊操作#

  1. 创建一个字符串去重工具 fn str.NewFilter(): *filter.StringFilter
  2. 【重要】:Grok 支持 fn str.Grok(var_1: string, var_2: string): yaklib.GrokResult

函数表以及用法#

f#

用法同 Golang fmt.Sprintf(fmt: string, vars: interface...) string; 略

EndsWith#

println(str.EndsWith("abcdef", "abc"))  // falseprintln(str.EndsWith("abcdef", "def"))  // true

IsStrongPassword#

判断一个字符串作为密码的话,算不算强密码

要求:

  1. 大于 8 位
  2. 包含特殊字符串
  3. 大小写同时包含
  4. 包含数字
println(str.IsStrongPassword("abcdefghijk"))       // falseprintln(str.IsStrongPassword("abc#52G"))           // falseprintln(str.IsStrongPassword("abcdefgh.G1ijk"))    // trueprintln(str.IsStrongPassword("abcdefghij.$t2Tk"))  // true

HostPort#

把域名或者IP+端口拼成一个网络地址

println(str.HostPort("192.168.1.1", 80))println(str.HostPort("192.168.1.1", "80"))println(str.HostPort("example.com", 80))println(str.HostPort("[::1]", 80))println(str.HostPort("::1", 80))println(str.HostPort("127.0.0.1", 80))
/*OUTPUT:
192.168.1.1:80192.168.1.1:80example.com:80[::1]:80[::1]:80127.0.0.1:80*/

IPv4ToCClassNetwork#

// 辅助打印结果def printTwoResult(res) {    arg1, err = res;    if err != nil {        println("ERR:", err)    } else {        println(arg1)    }}
printTwoResult(str.IPv4ToCClassNetwork("127.0.0.1"))printTwoResult(str.IPv4ToCClassNetwork("192.168.1.5"))printTwoResult(str.IPv4ToCClassNetwork("8.8.8.8"))printTwoResult(str.IPv4ToCClassNetwork("example.com"))printTwoResult(str.IPv4ToCClassNetwork("[::1]"))
/*OUTPUT:
127.0.0.0/24192.168.1.0/248.8.8.0/24ERR: invalid ipv4: example.comERR: invalid ipv4: [::1]*/

ParseStringToHostPort#

把字符串(URL/Addr)中的主机和端口解析出来

def printHostPortErr(res) {    host, port, err = res;    if err != nil {        println("ERROR: ", err)    }else{        printf("Host: %v Port: %v\n", host, port)    }}

printHostPortErr(str.ParseStringToHostPort("example.com:80"))printHostPortErr(str.ParseStringToHostPort("127.0.0.1:80"))printHostPortErr(str.ParseStringToHostPort("https://example.com"))printHostPortErr(str.ParseStringToHostPort("http://example.com"))printHostPortErr(str.ParseStringToHostPort("http://example.com:8082"))printHostPortErr(str.ParseStringToHostPort("example.com"))printHostPortErr(str.ParseStringToHostPort("example"))printHostPortErr(str.ParseStringToHostPort("127.0.0.1"))
/*OUTPUT:
Host: example.com Port: 80Host: 127.0.0.1 Port: 80Host: example.com Port: 443Host: example.com Port: 80Host: example.com Port: 8082ERROR:  unknown port for [example.com]ERROR:  unknown port for [example]ERROR:  unknown port for [127.0.0.1]*/

IsIPv4#

【略】

println(str.IsIPv4("127.0.0.1")) // trueprintln(str.IsIPv6("127.0.0.1")) // falseprintln(str.IsIPv6("::1"))       // trueprintln(str.IsIPv4("::1"))       // false

IsIPv6#

【略】


println(str.IsIPv4("127.0.0.1")) // trueprintln(str.IsIPv6("127.0.0.1")) // falseprintln(str.IsIPv6("::1"))       // trueprintln(str.IsIPv4("::1"))       // false

ParseStringToHosts#

把以,分割的字符串解析成主机信息,可解析内容为网段,IP,域名等。

一般用于解析扫描目标主机。

println(str.ParseStringToHosts("baidu.com,127.0.0.1,192.168.1.2/28"))// OUTPUT// [baidu.com 127.0.0.1 192.168.1.0 192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4 192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8 192.168.1.9 192.168.1.10 192.168.1.11 192.168.1.12 192.168.1.13 192.168.1.14 192.168.1.15]
println(str.ParseStringToHosts("10.3.0.1/24,8.8.8.8,example.com"))// OUTPUT// [10.3.0.0 ........ 10.3.0.246 10.3.0.247 10.3.0.248 10.3.0.249 10.3.0.250 10.3.0.251 10.3.0.252 10.3.0.253 10.3.0.254 10.3.0.255 8.8.8.8 example.com]
println(str.ParseStringToHosts("example.com,example2.com"))// OUTPUT// [example.com example2.com]

ParseStringToPorts#

println(str.ParseStringToPorts("22,3306,80-82,8080-8083"))println(str.ParseStringToPorts("8080-8083"))println(str.ParseStringToPorts("22,xx"))println(str.ParseStringToPorts("127.0.0.1/28"))
/*OUTPUT:
[22 80 81 82 3306 8080 8081 8082 8083][8080 8081 8082 8083][22][]*

ParseStringToLines#

解析成行

dump(str.ParseStringToLines("123123123\nasdfasdf\nwfhiuqwe\nasdfasdf\r\nasdfasdf"))/*OUTPUT:
([]string) (len=5 cap=8) { (string) (len=9) "123123123", (string) (len=8) "asdfasdf", (string) (len=8) "wfhiuqwe", (string) (len=8) "asdfasdf", (string) (len=8) "asdfasdf"}*/

ParseStringToUrls#

字符串生成可能的 URL

println(str.ParseStringToUrls("www.baidu.com"))println(str.ParseStringToUrls("example.com"))println(str.ParseStringToUrls("example.com:80"))println(str.ParseStringToUrls("sdfaasdgasd"))println(str.ParseStringToUrls("127.0.1.1"))println(str.ParseStringToUrls("192.168.1.3:443"))println(str.ParseStringToUrls("192.168.1.3:80"))
/*OUTPUT:
[https://www.baidu.com http://www.baidu.com][https://example.com http://example.com][http://example.com][https://sdfaasdgasd http://sdfaasdgasd][https://127.0.1.1 http://127.0.1.1][https://192.168.1.3][http://192.168.1.3]*/

ParseStringToUrlsWith3W#

println(str.ParseStringToUrlsWith3W("www.baidu.com"))println(str.ParseStringToUrlsWith3W("example.com"))println(str.ParseStringToUrlsWith3W("example.com:80"))println(str.ParseStringToUrlsWith3W("sdfaasdgasd"))println(str.ParseStringToUrlsWith3W("127.0.1.1"))println(str.ParseStringToUrlsWith3W("192.168.1.3:443"))println(str.ParseStringToUrlsWith3W("192.168.1.3:80"))
/*OUTPUT:
[https://www.baidu.com http://www.baidu.com][https://example.com https://www.example.com http://example.com http://www.example.com][http://example.com http://www.example.com][https://sdfaasdgasd https://www.sdfaasdgasd http://sdfaasdgasd http://www.sdfaasdgasd][https://127.0.1.1 http://127.0.1.1][https://192.168.1.3][http://192.168.1.3]*/