【问题标题】:C++ imitating ls like commandsC++ 模仿 ls 之类的命令
【发布时间】:2010-05-11 08:06:02
【问题描述】:

ls "filename_[0-5][3-4]?" 类如何实现?我想将结果存储在 vector 中。

目前我正在使用调用 lssystem(),但这在 MS 下不可移植。

谢谢, 阿曼。

【问题讨论】:

  • 这是一个全局模式吗?模式的[4-3] 部分可能无法达到您的预期。它的计算结果是文字 [4-3],所以也许你的意思是 [3-4],意思是 3 或 4。
  • 我不确定ls类的相似之处。对我来说,它更像是一种算法,因此更像是一个函数。

标签: c++ stl boost system


【解决方案1】:

以下程序列出当前目录中名称与正则表达式filename_[0-5][34]匹配的文件:

#include <boost/filesystem.hpp>
#include <boost/regex.hpp>  // also functional,iostream,iterator,string
namespace bfs = boost::filesystem;

struct match : public std::unary_function<bfs::directory_entry,bool> {
    bool operator()(const bfs::directory_entry& d) const {
        const std::string pat("filename_[0-5][34]");
        std::string fn(d.filename());
        return boost::regex_match(fn.begin(), fn.end(), boost::regex(pat));
    }
};

int main(int argc, char* argv[])
{
    transform_if(bfs::directory_iterator("."), bfs::directory_iterator(),
                 std::ostream_iterator<std::string>(std::cout, "\n"),
                 match(),
                 mem_fun_ref(&bfs::directory_entry::filename));
    return 0;
}

为简洁起见,我省略了transform_if() 的定义。它不是标准功能,但应该很容易实现。

【讨论】:

  • 当你尝试编译这个时,记得添加评论中提到的缺少的#include,定义缺少的transform_if()(如果需要我可以帮助你),并链接到文件系统和正则表达式库。使用 g++,您可以通过在命令行中指定 -lboost_filesystem -lboost_system -lboost_regex 来链接这些库。如果您使用的是 Linux,则可能不需要 -lboost_system 标志。
  • 这太不可思议了!!!适用于 linux 和 MS。谢谢!顺便说一句:我使用的 transform_if 是这样的: template Out transform_if(In first,In last,Out res,Pred p,Op op) { while(first!=last){ if (p(*first)) *res = op(*first); ++第一;++res; } 返回资源; }
【解决方案2】:

您可以使用 boost::filesystem,它具有一种可移植的方式来检索目录中的文件。

然后您可以使用 boost::regex 对照正则表达式检查文件,例如只保留与您的模式匹配的文件。

【讨论】:

  • 谢谢,我对正则表达式不熟悉,你能举一个解析我的模式的例子吗?
  • 你可以查看 boost:boost.org/doc/libs/1_43_0/libs/regex/doc/html/boost_regex/… 的文档,据我所知,它与“filename_[0-5][3-4]”没有太大区别
  • 事实上,这个 glob 模式恰好也是一个正则表达式。您可以将 [3-4] 更改为 [34] 并保持相同的含义,但除此之外它恰好保持不变。
【解决方案3】:

boost 解决方案是可移植的,但在 Windows 上不是最佳的。原因是它调用FindFirstFile("*.*") 并因此返回所有内容。鉴于通配模式,调用FindFirstFile("filename_?*.*") 会更有效。您仍然必须过滤结果(使用例如 Boost::regex),但这会排除许多不可能匹配的文件。

另外,使用任何一种方法都不要忘记在进行正则表达式匹配之前过滤掉目录。检查条目是否为目录非常便宜。

【讨论】:

  • 真的吗?即使boost::filesystem::directory_iterator?我可以看到在 OS X 上并非如此。
  • 我可能误解了您的评论,但当我解释 Windows 上的 Boost 不是最佳的地方时,我不明白 OSX 为何如此重要。
  • 我没有反驳你。我只是说在 OS X 上不是这样。寒意。
  • 感谢您指出性能问题。就我个人而言,在 MS 上的表现并不重要。所有生产运行都在 linux 上运行。
  • @WilhelmTell:啊哈,现在我明白了。基本上,Win32 API 接受过滤器作为输入,但 POSIX readdirboost::filesystem::directory_iterator::directory_iterator 都不接受。因此,在 Windows Boost 上必须使用 POSIX 上隐含的“.”模式。
猜你喜欢
  • 2011-12-07
  • 1970-01-01
  • 2020-07-25
  • 2016-07-25
  • 2014-05-30
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
相关资源
最近更新 更多