diff --git a/data/system/address/v1.xlsx b/data/system/address/v1.xlsx index ade97c80ce9d748ce8ce17f6792f297f2abf1404..083d2fc1c585f2dcd26529538db878a01d39473e 100644 Binary files a/data/system/address/v1.xlsx and b/data/system/address/v1.xlsx differ diff --git a/res/doc/sample.yaml b/res/doc/sample.yaml index 0d6642195722c59dbb2606fa638a0e79e4e8aed7..04ba362766d7edd17cc19b5901aa1708e889d484 100644 --- a/res/doc/sample.yaml +++ b/res/doc/sample.yaml @@ -1,14 +1,124 @@ -title: test -desc: This is a test file. +title: zendata数据配置语法说明 +desc: + + # 文件组成 + + # zendata以yaml格式的文件来定义各个字段的格式。 + # yaml文件整体由文件说明和字段定义两部分组成。 + + # 文件说明 + + # title: 标题,可以用简短的文字概要描述该文件定义的数据类型。 + # desc: 描述,可以用多行文本来详细描述该文件定义的数据类型,非必选项。 + # author: 作者,非必选项。 + # version:版本号,非必选项。 + + # 字段列表 + + # 字段定义部分都放在fields这个定义里面。 + # 一个yaml文件可以包含一个或者多个字段。 + # 字段列表以-field定义开始。 + # 一个字段可以通过fields属性定义它的子字段。 + + # 字段定义 + + # field: 字段名,仅支持英文、数字、下换线和. + # range: 列表范围,最重要的定义。 + # loop: 循环次数,可以定义某一字段循环多少次。 + # loopfix: 每一次循环时的连接符。 + + # format: 支持格式化输出。 + + # prefix: 该字段的前缀。 + # postfix: 该字段的后缀。 + + # length: 该字段的长度。如果不通过分隔符区分,则需要指定字段长度,单位是字节。 + # leftpad: 左填充的字符。如果长度不够,可指定左填充的字符。默认是以空格左填充。 + # rightpad: 右填充的字符。如果长度不够,可指定右填充的字符。 + + # config: 可以引用另外一个文件里面的定义。 + + # from: 引用某一个定义文件。 + # use: 使用被引用文件中定义的若干实例。all代表使用所有。 + # select: 如果引用的文件是excel表,可以查询里面的某一个字段。 + # where: 如果引用的文件是excel表,可以使用查询条件。 + + # range定义 + + # 使用逗号连接不同的元素。比如 range: 1,2,3 + # 元素也可以是一个区间。比如 range:1-10, A-Z + # 区间可以通过冒号:来指定步长。比如 range:1-10:2。 + # 步长可以是小数。比如 range: 1-10:0.1 + # 区间可以通过R来指定随机。比如 range: 1-10:R,随机和步长只能二选一。 + # 可以通过一个文件来指定列表。比如range: list.txt。文件名是相对路径时,以配置文件为基准计算。 + # 可以通过{n}的方式来重复某一个元素。比如 range: user1{100},user2{100} + # 如果区间或者几个元素需要重复,需要用[]括起来。比如 range: [user1,user2,user3]{100} + author: zentao version: 1.0 fields: - - field: field1 - note: 字符区间步长、随机 - range: a-f:R,0-9:2 - format: "%3d" - loop: 3 - loopfix: "," - prefix: "[" - postfix: "] " \ No newline at end of file + + - field: field_common # 默认的列表类型,通过逗号隔成若干区段。 + range: 1-10, 20-25, 27, 29, 30 # 1,2,3...,10,20,21,22...,25,27,29.30 + prefix: int_ # 前缀 + postfix: \t # 后缀 + + - field: field_step # 区间可以指定步长。 + range: 1-10:2, 1-2:0.1 # 1,3,5,7,9,1, 1.1,1.2...,2 + + - field: field_random # 通过R属性指定随机。R属性和步长不能同时出现。 + range: 1-10:R # 1,5,8... + + - field: field_file # 从一个文件中读取列表,并指定随机。 + range: _users.txt:R # 该文件中一行作为一个元素,并随机。 + + - field: field_loop # 自循环的字段。 + range: a-z # a_b_c | d_e_f | g_h_i + loop: 3 # 循环三次 + loopfix: _ # 每次循环的连接符。 + postfix: "|" # 特殊字符加引号,否则无法解析。 + + - field: field_repeat # 通过{}定义重复的元素。 + range: user-1{3},[user2,user3]{2} # user-1,user-1,user-1,user2,user3,user2,user3 + + - field: field_format # 通过格式化字符串输出。 + range: 1-10 # passwd 1,passwd 2,passwd 3 ... passwd10。 + format: "passwd%02d" # 用%2d补零,使密码整体保持8位,%2d默认补空格。 + + - field: field_use_another_file # 可以引用其他的定义文件。 + config: _numb_field.yaml # 引用当前目录下面的_numb_field.yaml文件里面的定义。 + + - field: field_use_ranges_file # 引用其他的定义文件,该文件定义了多个range,他们共享了一些field层面的属性。 + from: _numb_ranges.yaml # 引用当前目录下面的_numb_field.yaml文件里面的定义。 + use: medium # 使用该文件中定义的medium分组。 + + - field: field_use_instance # 引用其他的定义文件,该文件定义了多个实例。 + from: system.ip.v1.yaml # 引用data/system/ip/v1.yaml + use: privateC,privateC # 使用该文件中定义的privateC和privateB两个实例。 + + - field: field_use_excel # 从excel数据源里面取数据。 + from: system.address.v1.china # 从data/system/address/v1.xlsx文件中读取名为china的工作簿。 + select: city # 查询city字段。 + where: state like '%山东%' # 条件是 省份包含山东。 + + - field: field_with_children # 嵌套字段 + fields: + - field: child1 + range: a-z + prefix: part1_ + postfix: '|' + + - field: child2 + range: A-Z + prefix: part2_ + postfix: '|' + + - field: child_with_child + prefix: part3_ + postfix: + fields: + - field: field_grandson + prefix: int_ + range: 10-20 + postfix: diff --git a/res/doc/sample_en.yaml b/res/doc/sample_en.yaml new file mode 100644 index 0000000000000000000000000000000000000000..68f0d69b51c2191b775af8406014a35344958e8e --- /dev/null +++ b/res/doc/sample_en.yaml @@ -0,0 +1,124 @@ +title: zendata config syntax +desc: + + # File composition + + # zendata defines the format for each field in YAML file. + # YAML file is composed of file description and field definition. + + # File description + + # title: A short text to summarize the data type defined by this file. + # desc: Detailed text to describe the data type defined in this file, optional. + # author: Optional. + # version: Version number, optional. + + # Field list + + # Field is defined in fields. + # A YAML file contains one or more fields. + # Field list starts from -field. + # A child field can be defined by fields. + + # Field definition + + # field: Field name; letters, digits, underlines and dots only. + # range: List range; the most important definition. + # loop: The number of loops; define how many times a field can loop. + # loopfix: The connector for each loop. + + # format: Support formatted output. + + # prefix: Prefix of this field. + # postfix: Postfix of this field. + + # length: The length of this field. If separators are not used, specify the field length in bytes. + # leftpad: Left-padded characters. If the length is not enough, specify a character. The default is space. + # rightpad: Right-padded characters. If the length is not enough, specify a character. + + # config: Refer to the definition in other file. + + # from: Refer to a definition file. + # use: Use instances defined in the referred file. + # select: If refer to an excel table, you can query a field in it. + # where: If refer to an excel table, you can use query conditions. + + # range definition + + # Use commas to connect elements. e.g. range: 1,2,3. + # Elements can be a range, e.g. range:1-10, A-Z. + # Use colons to define steps, e.g. range:1-10:2. + # Steps can be decimals, e.g. range: 1-10:0.1. + # Intervals can be set as random by R, e.g. range: 1-10:R. Set either random or a specified step. + # Use a file to specify a list, e.g. range: list.txt. If the file name is a relative path, it is based on the config file. + # Use {n} to repeat a element, e.g. range: user1{100},user2{100}. + # Use [], if intervals and elements are repeated, e.g. range: [user1,user2,user3]{100}. + +author: zentao +version: 1.0 + +fields: + + - field: field_common # The list type by default. Separated by commas. + range: 1-10, 20-25, 27, 29, 30 # 1,2,3...,10,20,21,22...,25,27,29.30 + prefix: int_ # Prefix + postfix: \t # Postfix + + - field: field_step # Interval steps can be specified. + range: 1-10:2, 1-2:0.1 # 1,3,5,7,9,1, 1.1,1.2...,2 + + - field: field_random # Use R to specify randomly. Set either R or a specified step. + range: 1-10:R # 1,5,8... + + - field: field_file # Read a list from a file and set it as random. + range: _users.txt:R # Using the lines of users.txt as range and set it as random. + + - field: field_loop # Self-loop field. + range: a-z # a_b_c | d_e_f | g_h_i + loop: 3 # Loop three times. + loopfix: _ # The connector for each loop. + postfix: | + + - field: field_repeat # Use {} to define repeated elements. + range: user-1{3},[user2,user3]{2} # user-1,user-1,user-1,user2,user3,user2,user3 + + - field: field_format # Output as formatted strings. + range: 1-10 # passwd 1,passwd 2,passwd 3 ... passwd10。 + format: "passwd%02d" + + - field: field_use_another_file # Other definition file can be referred. + config: _numb_field.yaml # Refer to the definition in nubmer.yaml of the current directory. + + - field: field_use_ranges_file # Other definition file can be referred, in which more than one ranges are defined. + from: _numb_ranges.yaml # Refer to the definition in _numb_ranges.yaml of the current directory. + use: medium # use medium range. + + - field: field_use_instance # Refer to other definition file which defines multiple instances. + from: system.ip.v1.yaml # Refer to data/system/ip/v1.yaml. + use: privateB,privateC # Use the two instances of privateC and privateB defined in this file. + + - field: field_use_excel # Read the data from the data source of excel. + from: system.address.v1.china # Read the book named china in data/system/address/v1.xlsx. + select: city # Query the field city. + where: cityCode = 852 # Query condition. + + - field: field_with_children # Embeded field. + fields: + - field: child1 + range: a-z + prefix: part1_ + postfix: '|' + + - field: child2 + range: A-Z + prefix: part2_ + postfix: '|' + + - field: child_with_child + prefix: part3_ + postfix: + fields: + - field: field_grandson + prefix: int_ + range: 10-20 + postfix: diff --git a/res/messages_en.json b/res/messages_en.json index 7ff9e4035997905e7a7d4498f15329540e7b8bd1..af782313dd739f3bef5d116d3304ded714e55e1d 100644 --- a/res/messages_en.json +++ b/res/messages_en.json @@ -39,6 +39,10 @@ "id": "fail_to_read_file", "translation": "Fail to read file %s." }, + { + "id": "fail_to_write_file", + "translation": "Fail to write file %s." + }, { "id": "fail_to_parse_file", "translation": "Fail to parse the content of file %s." diff --git a/res/messages_zh.json b/res/messages_zh.json index e40d0d5e109b5825f566f96d55526c51a3640b91..075cde0438815b4730f474ddaa054cd0cf4c1325 100644 --- a/res/messages_zh.json +++ b/res/messages_zh.json @@ -34,6 +34,10 @@ "id": "fail_to_read_file", "translation": "读取文件%s失败。" }, + { + "id": "fail_to_write_file", + "translation": "写文件%s失败。" + }, { "id": "fail_to_parse_file", "translation": "解析文件%s失败。" diff --git a/src/service/md5.go b/src/service/md5.go new file mode 100644 index 0000000000000000000000000000000000000000..449565412e46d37a3c1cd17b7272f41ec1ff3039 --- /dev/null +++ b/src/service/md5.go @@ -0,0 +1,64 @@ +package service + +import ( + "crypto/md5" + "encoding/hex" + "github.com/360EntSecGroup-Skylar/excelize/v2" + i118Utils "github.com/easysoft/zendata/src/utils/i118" + logUtils "github.com/easysoft/zendata/src/utils/log" + "strconv" + "strings" +) + +const ( + md5Col = "CW" +) + +func AddMd5(path string, salt string) { + excel, err := excelize.OpenFile(path) + if err != nil { + logUtils.Screen(i118Utils.I118Prt.Sprintf("fail_to_read_file", path)) + return + } + + for _, sheet := range excel.GetSheetList() { + rows, _ := excel.GetRows(sheet) + + colCount := 0 + for index, row := range rows { + if index == 0 { // deal with the title + for _, col := range rows[index] { + val := strings.TrimSpace(col) + if val == "" { break } + colCount++ + } + continue + } + + if row[0] == "" { // stop when finding a blank in first column + break + } + + str := "" + for idx, col := range row { + if idx >= colCount { break } + + val := strings.TrimSpace(col) + str = str + val + } + md5Str := md5V(str, salt) + excel.SetCellValue(sheet, md5Col + strconv.Itoa(index + 1), md5Str) + } + } + + if err := excel.SaveAs(path); err != nil { + logUtils.Screen(i118Utils.I118Prt.Sprintf("fail_to_write_file", path)) + } +} + +func md5V(str, salt string) string { + h := md5.New() + h.Write([]byte(str)) + h.Write([]byte(salt)) + return hex.EncodeToString(h.Sum(nil)) +} \ No newline at end of file diff --git a/src/utils/log/print.go b/src/utils/log/print.go index 3915ee0ac9e5adfde60ad64740a4b9571c560c92..a322b13a8279cdd27b8601e82978b3dd35b652ca 100644 --- a/src/utils/log/print.go +++ b/src/utils/log/print.go @@ -5,6 +5,7 @@ import ( "fmt" commonUtils "github.com/easysoft/zendata/src/utils/common" fileUtils "github.com/easysoft/zendata/src/utils/file" + "github.com/easysoft/zendata/src/utils/vari" "github.com/fatih/color" "os" "regexp" @@ -17,19 +18,27 @@ var ( ) func PrintExample() { + if vari.Config.Language == "en" { + exampleFile = strings.Replace(exampleFile, ".yaml", "_en.yaml", -1) + usageFile = strings.Replace(usageFile, ".txt", "_en.txt", -1) + } + content := fileUtils.ReadResData(exampleFile) fmt.Printf("%s\n", content) } func PrintUsage() { - //PrintToWithColor(i118Utils.I118Prt.Sprintf("usage"), color.FgCyan) + if vari.Config.Language == "en" { + exampleFile = strings.Replace(exampleFile, ".yaml", "_en.yaml", -1) + usageFile = strings.Replace(usageFile, ".txt", "_en.txt", -1) + } usage := fileUtils.ReadResData(usageFile) exeFile := "zd" if commonUtils.IsWin() { exeFile += ".exe" } - usage = fmt.Sprintf(usage, exeFile) + if !commonUtils.IsWin() { regx, _ := regexp.Compile(`\\`) usage = regx.ReplaceAllString(usage, "/") diff --git a/src/zd.go b/src/zd.go index 24df7208fa6e99eada4969732926f47ce2d26572..9a3a4d1de1cdb66cc887e60bfa3f5429d4d3359a 100644 --- a/src/zd.go +++ b/src/zd.go @@ -38,6 +38,8 @@ var ( listRes bool viewRes string viewDetail string + md5 string + salt string example bool help bool @@ -83,6 +85,9 @@ func main() { flagSet.StringVar(&viewRes, "v", "", "") flagSet.StringVar(&viewRes, "view", "", "") + flagSet.StringVar(&md5, "md5", "", "") + flagSet.StringVar(&salt, "salt", "", "") + flagSet.StringVar(&vari.HeadSep, "H", "", "") flagSet.StringVar(&vari.HeadSep, "human", "", "") @@ -126,6 +131,9 @@ func main() { } else if viewRes != "" { service.ViewRes(viewRes) return + } else if md5 != "" { + service.AddMd5(md5, salt) + return } if vari.Ip != "" || vari.Port != 0 {