使用C 等级进行多匹配
Using C++ regex for multi match
本文关键字:使用 更新时间:2023-10-16
我想解析相对简单的注册表文件格式,让我们假设它是普通的ascii,以旧的regedit4格式保存。我想使用标准的C 正则函数或功能(最好无提升)对其进行解析。作为输入数据,可以以这样的示例文件为例:
REGEDIT4
[HKEY_LOCAL_MACHINESOFTWAREMyCompanyConfigurationDatav1.0]
[HKEY_LOCAL_MACHINESOFTWAREMyCompanyConfigurationDatav1.0General]
"SettingDword"=dword:00000009
"Setting1"="Some string 1"
"SettingString2"="my String"
[HKEY_LOCAL_MACHINESOFTWAREMyCompanyConfigurationDatav1.0Networking]
"SettingDword2"=dword:00000002
"Setting2"="Some string 2"
"SettingString3"="my String2"
我已经简要分析了 - 可以使用例如cregex_token_iterator
类扫描多个[],但是主要问题是它以相反的方式工作,我想使用它。我想开始这样的匹配模式:regex re("(\[.*?\])")
,但是令牌迭代器返回所有不匹配的字符串,对我来说听起来很愚蠢。
基本上,我想匹配整个部分(\[.*?\])(.*?nn)
,然后首先访问注册表路径,然后接下来 - 然后使用Regex键值对分开。
在C#中,像这样编写Regex Matcher相对容易,但我更喜欢与C 一起使用,因为它是本地的,没有性能和组装卸载问题。
终于进行了交叉分析 - 可以使用regex_search
,但是搜索需要通过从下一个char*继续进行的搜索来重述。
下面几乎是加载.REG文件在运行时的完整示例,我正在使用MFC的CString
,因为它比std::string
更容易使用,并且当前不需要可移植性。
#include "stdafx.h"
#include <afx.h> //CFile
#include "TestRegex.h"
#include <fstream>
#include <string>
#include <regex>
#include <map>
CWinApp theApp;
using namespace std;
typedef enum
{
eREG_DWORD = REG_DWORD,
eREG_QWORD = REG_QWORD,
eREG_BINARY = REG_BINARY,
eREG_SZ = REG_SZ
}eRegType;
class RegVariant
{
public:
eRegType type;
union
{
DWORD dw;
__int64 qw;
};
CStringA str;
};
class RegKeyNode
{
public:
// Paths to next nodes
map<CStringA, RegKeyNode> keyToNode;
// Values of current key
map<CStringA, RegVariant> keyValues;
};
map<HKEY, RegKeyNode> g_registry;
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return 0;
}
void hexToBin( const char* hex, CStringA& bin, int maxSize = -1 )
{
int size = (strlen(hex) + 1)/ 3;
if(maxSize != -1 && size > maxSize)
size = maxSize;
unsigned char* buf = (unsigned char*)bin.GetBuffer(size);
for( int i = 0; i < size; i++ )
buf[i] = char2int( hex[ i*3 ] ) * 16 + char2int(hex[i * 3 + 1]);
bin.ReleaseBuffer();
}
int main()
{
HMODULE hModule = ::GetModuleHandle(nullptr);
AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0);
//
// Load .reg file.
//
CString fileName = L"test1.reg";
CStringA file;
CFile cfile;
if (cfile.Open(fileName, CFile::modeRead | CFile::shareDenyNone))
{
int len = (int)cfile.GetLength();
cfile.Read(file.GetBuffer(len), len);
file.ReleaseBuffer();
}
cfile.Close();
file.Replace("rn", "n");
const char* pbuf = file.GetBuffer();
regex reSection("\[(.*?)\]([^]*?)nn");
regex reLine("^\s*"(.*?)"\s*=\s*(.*)$");
regex reTypedValue("^(hex|dword|hex\(b\)):(.*)$");
regex reStringValue("^"(.*)"$" );
cmatch cmSection, cmLine;
//
// For each section:
//
// [registry path]
// "value1"="value 1"
// "value2"="value 1"
//
while( regex_search(pbuf, pbuf + strlen(pbuf), cmSection, reSection) )
{
CStringA path = cmSection[1].str().c_str();
string key_values = cmSection[2].str();
const char* pkv = key_values.c_str();
int iPath = 0;
CStringA hkeyName = path.Tokenize("\", iPath).MakeUpper();
RegKeyNode* rnode;
if( hkeyName.Compare("HKEY_LOCAL_MACHINE") == 0 )
rnode = &g_registry[HKEY_LOCAL_MACHINE];
else
rnode = &g_registry[HKEY_CURRENT_USER]; // Don't support other HKEY roots.
//
// Locate path where to place values.
//
for( ; hkeyName = path.Tokenize("\", iPath); )
{
if( hkeyName.IsEmpty() )
break;
rnode = &rnode->keyToNode[hkeyName];
}
//
// Scan "key"="value" pairs.
//
while( regex_search(pkv, pkv+strlen(pkv), cmLine, reLine ))
{
CStringA key = cmLine[1].str().c_str();
string valueType = cmLine[2].str();
smatch cmTypeValue;
RegVariant* rvValue = &rnode->keyValues[key];
//
// Extract type and value.
//
if(regex_search(valueType, cmTypeValue, reTypedValue))
{
string type = cmTypeValue[1].str();
string value = cmTypeValue[2].str();
if( type == "dword")
{
rvValue->type = eREG_DWORD;
rvValue->dw = (DWORD)strtoul(value.c_str(), 0, 16);
}
else if (type == "hex(b)")
{
rvValue->type = eREG_QWORD;
rvValue->qw = 0;
if( value.size() == 8 * 2 + 7 )
{
CStringA v;
hexToBin(value.c_str(), v, sizeof(__int64));
rvValue->qw = *((__int64*)v.GetBuffer());
}
} else //if (type == "hex")
{
rvValue->type = eREG_BINARY;
hexToBin(value.c_str(), rvValue->str);
}
} else if( regex_search(valueType, cmTypeValue, reStringValue))
{
rvValue->type = eREG_SZ;
rvValue->str = cmTypeValue[1].str().c_str();
}
pkv = cmLine[2].second;
} //while
pbuf = cmSection[2].second;
} //while
return 0;
}
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- C++:TypeDef使用元组
- 使用std::multimap迭代器创建std::list
- 从不同线程使用int64的不同字节安全吗
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在全局范围内使用"extern int a"似乎不行?
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用Google Mock来模拟gettimeofday()
- 如何使用默认参数等选择模板专业化
- 为什么使用 "this" 指针调用派生成员函数?
- 使用新行和不使用新行读取文件
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 如何确定我已使用非编码文件到达 EOF?
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 使用CMake创建QML插件
- 使用strcpy将char数组的元素复制到另一个数组
- 在c++中使用nlohmann从类到json的转换
- 使用指针从C++中的数组中获取最大值
- 使用不带参数的函数访问结构元素