借助五一假期,写了一个命令行解析的基础库,一般可用于串口命令解析、TCP命令解析等等。

具有以下几种特点:

  • 不涉及到具体硬件, 纯软件协议,与具体硬件分离。
  • 支持不定长命令行,逐个字符解码,可以支持不定长的命令参数解析。
  • 支持解析过程中,对字符进行大小写转换,便于支持命令行大小写不敏感。
  • 内存空间占用可控,可使用静态内存,也可以使用动态内存,内存空间可控。
  • 分割符可灵活定义,支持自定义分割符和忽略符号,面向对象设计,可多个实例应用。

源码仓库:
GitHub - lovemengx/libserial_parse_text: 适用于单片机实现串口命令行解析的基础库, 支持动静态内存方式适用于单片机实现串口命令行解析的基础库, 支持动静态内存方式. Contribute to lovemengx/libserial_parse_text development by creating an account on GitHub.https://github.com/lovemengx/libserial_parse_textlibserial_parse_text: 适用于单片机实现串口命令行解析的基础库https://gitee.com/lovemengx/libserial_parse_text一、接口说明

// 缓存大小包含了接口内部所使用的数据结构空间
typedef struct{
char *buf; // 缓存地址, 用于存储解析后的字符串
unsigned int total; // 缓存大小, 标明该内存空间的总长度
}libserial_parse_buf_t; #define LIBSERIAL_PARSE_SHIFT_NORMAL 0 // 不转换
#define LIBSERIAL_PARSE_SHIFT_LOWER 1 // 转换为小写字母
#define LIBSERIAL_PARSE_SHIFT_UPPER 2 // 转换为大写字母 /*---------------------------------------------------------------------
* 函数: libserial_parse_create
* 功能: 使用接口内部申请指定可用大小的空间(包含内部数据结构所用空间)
* 参数: size: 申请可用缓冲区大小
* 返回: NULL: 申请内存空间失败 >0: 申请成功
*---------------------------------------------------------------------*/
libserial_parse_buf_t *libserial_parse_create(unsigned int size); /*---------------------------------------------------------------------
* 函数: libserial_parse_release
* 功能: 释放接口内部申请的内存空间
* 参数: spbuf: 由 libserial_parse_create() 创建的内存空间
* 返回: 无返回值
*---------------------------------------------------------------------*/
void libserial_parse_release(libserial_parse_buf_t *spbuf); /*---------------------------------------------------------------------
* 函数: libserial_parse_internal_size
* 功能: 返回内部数据结构占用字节数
* 参数: 无需参数
* 返回: 内部数据结构占用字节数(不同字长的处理器可能不一样)
*---------------------------------------------------------------------*/
unsigned int libserial_parse_internal_size(); /*---------------------------------------------------------------------
* 函数: libserial_parse_init
* 功能: 使用用户提供的或创建接口的缓冲区, 初始化内部数据结构
* 参数: spbuf: 缓冲区 size: 缓冲区大小
* 返回: 0: 不满足最小长度要求 >0: 可存储最长文本的长度
* 备注: 默认设置忽略字符为: '\0', 默认设置分隔字符为: '\n'
*---------------------------------------------------------------------*/
unsigned int libserial_parse_init(libserial_parse_buf_t *spbuf); /*---------------------------------------------------------------------
* 函数: libserial_parse_reset_buf
* 功能: 重置解析器缓冲区
* 参数: spbuf: 缓冲区
* 返回: 无返回值
* 备注: 不影响 libserial_parse_set_divide()\libserial_parse_set_ignore()
*---------------------------------------------------------------------*/
void libserial_parse_reset_buf(libserial_parse_buf_t *spbuf); /*---------------------------------------------------------------------
* 函数: libserial_parse_set_divide
* 功能: 设定分隔字符
* 参数: splbuf: 缓冲区 divide: 分隔字符
* 返回: 无返回值
*---------------------------------------------------------------------*/
void libserial_parse_set_divide(libserial_parse_buf_t *spbuf, char divide); /*---------------------------------------------------------------------
* 函数: libserial_parse_set_ignore
* 功能: 设定忽略字符, 传入 '\0' 代表不忽略任何字符
* 参数: splbuf: 缓冲区 ignore: 忽略字符
* 返回: 无返回值
* 备注: 双引号内的字符不会受此限制
*---------------------------------------------------------------------*/
void libserial_parse_set_ignore(libserial_parse_buf_t *spbuf, char ignore); /*---------------------------------------------------------------------
* 函数: libserial_parse_set_shift
* 功能: 设置大小写字母转换
* 参数: splbuf: 缓冲区 shift: 0:不做转换 1:转换为小写字母 2:转换为大写字母
* 返回: 无返回值
*---------------------------------------------------------------------*/
void libserial_parse_set_shift(libserial_parse_buf_t *spbuf, char shift); /*---------------------------------------------------------------------
* 函数: libserial_parse_text
* 功能: 解析以指定符号分隔或跳过的文本
* 参数: splbuf: 缓冲区 indata: 输入数据
* 返回: 0: 正在解析 >0:解析完成, 返回文本长度(不包含 '\0')
* 备注: 没有设定分隔符则会一直返回0, 数据超出缓存长度会返回解析完成
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text(libserial_parse_buf_t *spbuf, char indata); /*---------------------------------------------------------------------
* 函数: libserial_parse_text_nl (nl -> new line)
* 功能: 解析以换行符为终止符的文本(支持 '\n' 和 '\r\n')
* 参数: splbuf: 缓冲区 indata: 输入数据
* 返回: 0: 正在解析 >0:解析完成, 返回文本长度(不包含 '\0')
* 备注: 不受 libserial_parse_set_divide()\libserial_parse_set_ignore() 影响
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text_nl(libserial_parse_buf_t *spbuf, char indata); /*---------------------------------------------------------------------
* 函数: libserial_parse_finish
* 功能: 获取当前仍在缓冲区的字符数据
* 参数: splbuf: 缓冲区
* 返回: 0: 没有数据 >0:剩余字符串长度(不包含 '\0')
*---------------------------------------------------------------------*/
unsigned int libserial_parse_text_finish(libserial_parse_buf_t *spbuf);

二、示例代码

#include <stdio.h>
#include "libserial_parse_text.h" #define iprintf(format,...) printf("[inf]%s():%05d " format , __func__, __LINE__,##__VA_ARGS__) /*---------------------------------------------------------------------
* 函数: dynamic_mem_newline_example
* 功能: 动态内存版本以行为分割符的示例代码
*---------------------------------------------------------------------*/
int dynamic_mem_newline_example(const char* string)
{
libserial_parse_buf_t* spbuf = NULL;
unsigned int len = 0x00, i = 0x00; // 创建缓冲区
if ((spbuf = libserial_parse_create(512)) == NULL) {
printf("reate parse buf failed.\n");
return -1;
} // 初始化缓冲区
if ((len = libserial_parse_init(spbuf)) == 0x00) {
printf("memory is too small.\n");
libserial_parse_release(spbuf);
return -1;
} // 开始解析字符串
printf("total:%d len:%d\n", spbuf->total, len);
for (i = 0; i < strlen(string); i++) {
if ((len = libserial_parse_text_nl(spbuf, string[i])) > 0) {
printf("[parse] : %-2d->[%s]\n", len, spbuf->buf);
}
} // 检查是否还有剩下的字符串
if ((len = libserial_parse_text_finish(spbuf)) > 0) {
printf("[finish]: %-2d->[%s]\n", len, spbuf->buf);
} // 释放动态内存
libserial_parse_release(spbuf);
return 0;
} /*---------------------------------------------------------------------
* 函数: static_mem_newline_example
* 功能: 静态内存版本以行为分割符的示例代码
*---------------------------------------------------------------------*/
int static_mem_newline_example(const char* string)
{
char buff[512] = { 0 };
libserial_parse_buf_t spbuf;
unsigned int len = 0x00, i = 0x00; // 指定静态内存
spbuf.buf = buff;
spbuf.total = sizeof(buff); // 初始化缓冲区
if ((len = libserial_parse_init(&spbuf)) == 0x00) {
printf("memory is too small.\n");
return -1;
} // 开始解析字符串
printf("total:%d len:%d\n", spbuf.total, len);
for (i = 0; i < strlen(string); i++) {
if ((len = libserial_parse_text_nl(&spbuf, string[i])) > 0) {
printf("[parse] : %-2d->[%s]\n", len, spbuf.buf);
}
} // 检查是否还有剩下的字符串
if ((len = libserial_parse_text_finish(&spbuf)) > 0) {
printf("[finish]: %-2d->[%s]\n", len, spbuf.buf);
} return 0;
} /*---------------------------------------------------------------------
* 函数: static_mem_divide_example
* 功能: 静态内存版本以自定义分割符的示例代码
*---------------------------------------------------------------------*/
int static_mem_divide_example(const char* string)
{
char buff[512] = { 0 };
libserial_parse_buf_t spbuf;
unsigned int len = 0x00, i = 0x00; // 指定静态内存
spbuf.buf = buff;
spbuf.total = sizeof(buff); // 初始化缓冲区
if ((len = libserial_parse_init(&spbuf)) == 0x00) {
printf("memory is too small.\n");
return -1;
} // 命令格式假定: 命令名称 参数1, 参数2, 参数3
libserial_parse_set_divide(&spbuf, ' '); // 设置分隔字符为空格, 提取命令名称
libserial_parse_set_ignore(&spbuf, '\0'); // 设置忽略字符为字符串结束符, 即不忽略任何字符 // 开始解析字符串
printf("total:%d len:%d\n", spbuf.total, len);
for (i = 0; i < strlen(string); i++) {
if ((len = libserial_parse_text(&spbuf, string[i])) > 0) {
printf("[parse] : %-2d->[%s]\n", len, spbuf.buf);
libserial_parse_set_divide(&spbuf, ','); // 设置分隔字符为逗号, 提取参数
libserial_parse_set_ignore(&spbuf, ' '); // 设置忽略字符为空格, 忽略参数中的空格字符
}
} // 检查是否还有剩下的字符串
if ((len = libserial_parse_text_finish(&spbuf)) > 0) {
printf("[finish]: %-2d->[%s]\n", len, spbuf.buf);
} return 0;
} // 解析命令
int serial_command_text(libserial_parse_buf_t* spbuf, const char* string)
{
unsigned int i = 0x00; for (i = 0; i < strlen(string); i++) {
if (libserial_parse_text(spbuf, string[i])) {
return 1;
}
} return !!libserial_parse_text_finish(spbuf);
} // 解析命令参数
int serial_exec_command(libserial_parse_buf_t* spbuf, const char* command, const char* paramet)
{
unsigned int i = 0x00; printf("[command]: [%s]\n", command); for (i = 0; i < strlen(paramet); i++) {
if (libserial_parse_text(spbuf, paramet[i])) {
printf("[paramet]: [%s]\n", spbuf->buf);
}
} if (libserial_parse_text_finish(spbuf)) {
printf("[paramet]: [%s]\n", spbuf->buf);
}
printf("\n"); // 执行命令代码...... return 0;
} /*---------------------------------------------------------------------
* 函数: serial_command_parse_example
* 功能: 动态内存版本完整的命令行解析示例代码
*---------------------------------------------------------------------*/
int serial_command_parse_example(const char* string)
{
unsigned int i = 0x00, j = 0x00;
libserial_parse_buf_t* spbuf1 = libserial_parse_create(256);
libserial_parse_buf_t* spbuf2 = libserial_parse_create(64);
libserial_parse_buf_t* spbuf3 = libserial_parse_create(256); // 初始化缓冲区
libserial_parse_init(spbuf1);
libserial_parse_init(spbuf2);
libserial_parse_init(spbuf3); // 命令格式假定: 命令名称 参数1,参数2,参数3
libserial_parse_set_divide(spbuf2, ' '); // 设置解析命令的分隔字符为空格, 提取命令名称
libserial_parse_set_ignore(spbuf2, '\0'); // 设置解析命令的忽略字符为字符串结束符, 即不忽略任何字符
libserial_parse_set_divide(spbuf3, ','); // 设置解析参数的分隔字符为逗号, 提取参数
libserial_parse_set_ignore(spbuf3, ' '); // 设置解析参数的忽略字符为空格, 忽略参数中的空格字符 // 模拟串口收到的数据
for (i = 0; i < strlen(string); i++)
{
// 解析字符串
if (libserial_parse_text_nl(spbuf1, string[i]) == 0) {
continue;
} // 解析命令
printf("[parse]: [%s]\n", spbuf1->buf);
if (serial_command_text(spbuf2, spbuf1->buf) == 0) {
continue;
} // 解析参数并执行命令
serial_exec_command(spbuf3, spbuf2->buf, spbuf1->buf + strlen(spbuf2->buf));
} // 释放缓冲区
libserial_parse_release(spbuf1);
libserial_parse_release(spbuf2);
libserial_parse_release(spbuf3); return 0;
} int main(void)
{
const char* string = "@ABCDEFGHIJKLAA@\n\nQQ:1007566569\r\nlovemengx@qq.com\n123456789#++++++.....";
const char* strcmd = "reg_w 0x01=0x20, 0x02= 0x15, 0x03=0x56";
const char* strcmds = "wifi \"my wifi\",12345678\nvideo udp,192.168.1.115,8000\nreg_w 0x01=0x20, 0x02= 0x15, 0x03=0x56\nreg_r 0x01,0x02,0x05,0x06\nreboot\n"; // 静态内存解析以行分隔的字符串示例
printf("------------------------------------\n");
printf("static memory newline example...\n");
printf("------------------------------------\n");
static_mem_newline_example(string); // 动态内存解析以行分隔的字符串示例
printf("------------------------------------\n");
printf("dynamic memory newline example...\n");
printf("------------------------------------\n");
dynamic_mem_newline_example(string);
printf("------------------------------------\n"); // 动态内存解析以自定义分隔和忽略的字符串示例
printf("------------------------------------\n");
printf("dynamic memory divide example...\n");
printf("------------------------------------\n");
static_mem_divide_example(strcmd);
printf("------------------------------------\n"); // 解析命令、参数并执行命令的完整示例
printf("------------------------------------\n");
printf("command parse example...\n");
printf("------------------------------------\n");
serial_command_parse_example(strcmds);
printf("------------------------------------\n"); return 0;
}

三、执行结果

【开源】libserial_parse_text:命令行解析的基础库的更多相关文章

  1. 【C++】cmdline——轻量级的C++命令行解析库

    1.说明 cmdline是一个轻量级的c++命令行参数解析工具,全部源码只有一个cmdline.h头文件. 2.代码 20171210_命令行进行解析.cpp // 20171210_命令行进行解析. ...

  2. Python命令行解析argparse常用语法使用简介

    查看原文:http://www.sijitao.net/2000.html python中的命令行解析最简单最原始的方法是使用sys.argv来实现,更高级的可以使用argparse这个模块.argp ...

  3. Python 命令行解析工具 Argparse介绍

    最近在研究pathon的命令行解析工具,argparse,它是Python标准库中推荐使用的编写命令行程序的工具. 以前老是做UI程序,今天试了下命令行程序,感觉相当好,不用再花大把时间去研究界面问题 ...

  4. python实现命令行解析的argparse的使用

    参考https://docs.python.org/3.6/library/argparse.html argparse模块使编写用户友好的命令行界面变得很容易.程序定义了它需要什么参数,argpar ...

  5. 使用命令行解析php文件

    使用命令行解析php文件,这样可以调用Log4PHP库中的一些demo,因为默认的输出使用命令行作为输出. 建一个bat文件: echo 以下是使用命令行解析php文件 C:\xampp\php\ph ...

  6. 『Argparse』命令行解析

    一.基本用法 Python标准库推荐使用的命令行解析模块argparse 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的optparse.因为argparse是 ...

  7. 2019-9-2-C#命令行解析工具

    title author date CreateTime categories C#命令行解析工具 lindexi 2019-09-02 12:57:37 +0800 2018-2-13 17:23: ...

  8. Go语言 命令行解析(一)

    命令行启动服务的方式,在后端使用非常广泛,如果有写过C语言的同学相信不难理解这一点!在C语言中,我们可以根据argc和argv来获取和解析命令行的参数,从而通过不同的参数调取不同的方法,同时也可以用U ...

  9. python模块----optparse模块、argparse模块 (命令行解析模块)

    简介 optparse module---自版本3.2以来已弃用:optparse模块已弃用,将不再进一步开发:将继续使用argparse模块进行开发.optparse使用一种更具声明性的命令行解析方 ...

  10. Noah的学习笔记之Python篇:命令行解析

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

随机推荐

  1. 三种梯度下降法的对比(BGD & SGD & MBGD)

    常用的梯度下降法分为: 批量梯度下降法(Batch Gradient Descent) 随机梯度下降法(Stochastic Gradient Descent) 小批量梯度下降法(Mini-Batch ...

  2. Redis的攻击手法

    目录 Redis概述 Redis未授权 漏洞发现 漏洞验证 Redis写shell 漏洞利用 Redis写公钥 漏洞利用 主从复制RCE 漏洞简介: 漏洞利用 计划任务反弹shell 漏洞利用 Red ...

  3. 软件开发-客观综合(GO)

    1 对从go源码和汇编源码生成可执行程序的过程,下面描述错误的是() ​A. 使用go tool compile可以将go源码编译成目标文件 B. 使用go tool asm可以将go源码编译成汇编代 ...

  4. oracle问题记录

    ORA-01034: ORACLE not available [oracle@ilanni ~]$ sqlplus /nolog SQL*Plus: Release 10.2.0.1.0 – Pro ...

  5. C#winform使用NOPI读取Excel读取图片

    需求:在Winform使用NOPI做导入时候,需要导入数据的同时导入图片. 虽然代码方面不适用(我好像也没仔细看过代码),但是感谢大佬给了灵感http://www.wjhsh.net/IT-Ramon ...

  6. linux 挂载 vdi 文件(virtual box虚拟机镜像文件)

    1. 下载 vdfuse 下载地址 2.解压deb文件 解压deb安装包文件,这里不使用安装命令是因为你的virtualbox 可能和vdfuse的版本不一致,导致安装失败,而我们只需要用到 vdfu ...

  7. 《浅谈亚 log 数据结构在 OI 中的应用》阅读随笔

    这篇又长长长了! \(8435\to 8375\to 9729\) 早就馋这篇了!终于学了( 压位 Trie 确实很好写啊 但是总感觉使用范围不是很广的样子 似乎是见的题少 原文里都在用 \(\log ...

  8. hexo-gitalk-评论自动初始化

    第一步 申请Personal Access Token 从 Github 的 Personal access tokens 页面,点击 Generate new token 第二步 安装项目依赖 np ...

  9. <七>lambda表达式实现原理

    C++11 函数对象的升级版=>lambda表达式 函数对象的缺点: 使用在泛型算法,参数传递, 比较性质/自定义操作 优先级队列, 需要专门定义出一个类 //lambda表达式语法: //[捕 ...

  10. [opencv]一些重配遇到的问题(只针对我自己的电脑)

    1.我的opencv版本是4.5.3 2.环境变量这样配 3.对于每个项目,项目属性这样配: 其中包含目录: C:\Users\dxd\OPCV\opencv\build\include\opencv ...