如何从libssh2_sftp_readdir_ex()输出中提取仅文件与目录名称
最优实现方案(无正则,性能更高,兼容含空格的文件名)
你拿到的每条条目是标准的ls -l格式输出,前8个固定为空格分隔的属性字段(权限、硬链接数、属主、属组、文件大小、月份、日期、时间),从第9个位置开始到行尾的所有内容都是文件名,哪怕文件名本身包含空格也能正确提取。
实现代码如下:
#include <string> #include <vector> #include <cctype> // ... 你的其他业务代码 for (const auto& line : LSEntriesFull) { size_t pos = 0; int field_count = 0; const size_t len = line.size(); // 跳过前8个属性字段 while (field_count < 8 && pos < len) { // 跳过字段前的所有连续空格 while (pos < len && std::isspace(static_cast<unsigned char>(line[pos]))) { pos++; } // 跳过当前字段的所有非空格内容 while (pos < len && !std::isspace(static_cast<unsigned char>(line[pos]))) { pos++; } field_count++; } // 跳过文件名前的剩余空格,剩下的内容就是完整文件名 while (pos < len && std::isspace(static_cast<unsigned char>(line[pos]))) { pos++; } if (pos < len) { LSEntriesBrief.emplace_back(line.substr(pos)); } }
沿用正则写法的修正方案
如果你更习惯用正则实现,可以直接匹配提取文件名部分,不需要拆分所有字段,逻辑更简洁:
#include <regex> #include <string> #include <vector> // ... 你的其他业务代码 // 正则匹配规则:跳过前8个空格分隔的字段后,捕获剩余所有内容为文件名 // 注:用了C++11及以上支持的原始字符串字面量,低版本标准需转义为 "^(?:\\S+\\s+){8}(.+)$" const std::regex file_name_re(R"(^(?:\S+\s+){8}(.+)$)"); std::smatch match; for (const auto& line : LSEntriesFull) { if (std::regex_match(line, match, file_name_re)) { LSEntriesBrief.emplace_back(match[1].str()); } }
原代码错误原因
- 用空格拆分所有字段后,重复调用
itr++会跳过部分字段,还可能出现迭代器越界问题 - 没有过滤前8个属性字段,直接把所有拆分后的字段都存入了目标向量
- 拆分逻辑无法兼容文件名带空格的场景,会把单个文件名拆成多个错误条目存入
内容的提问来源于stack exchange,提问作者fborges22
相关产品推荐
相关产品推荐

