【问题标题】:extract domain between two words提取两个词之间的域
【发布时间】:2012-07-19 21:36:36
【问题描述】:

我在一个日志文件中有这样几行:

11-test.domain1.com 已记录...

37-user1.users.domain2.org 记录...

48-me.server.domain3.net 记录...

如何在没有子域的情况下提取每个域?介于“-”和“Logged”之间的东西

我在 c++ (linux) 中有以下代码,但它不能很好地提取。如果你有一些例子,一些返回提取字符串的函数会很棒。

       regex_t    preg;
       regmatch_t mtch[1];
       size_t     rm, nmatch;
       char tempstr[1024] = "";
       int start;
       rm=regcomp(&preg, "-[^<]+Logged", REG_EXTENDED);
       nmatch = 1;
       while(regexec(&preg, buffer+start, nmatch, mtch, 0)==0) /* Found a match */
               {
                 strncpy(host, buffer+start+mtch[0].rm_so+3, mtch[0].rm_eo-mtch[0].rm_so-7);
                 printf("%s\n", tempstr);
                 start +=mtch[0].rm_eo;
                 memset(host, '\0', strlen(host));
               }
       regfree(&preg);

谢谢!

附:不,我不能为此使用 perl,因为这部分位于由其他人制作的更大的 c 程序中。

编辑:

我用这个替换代码:

   const char *p1 = strstr(buffer, "-")+1;
   const char *p2 = strstr(p1, " Logged");
   size_t len = p2-p1;
   char *res = (char*)malloc(sizeof(char)*(len+1));
   strncpy(res, p1, len);
   res[len] = '\0';

这很好地提取了包括子域在内的整个域。 如何从 abc.def.domain.com 中仅提取 domain.com 或 domain.net ?

strtok 是一个不错的选择吗?如何计算最后一个点?

【问题讨论】:

  • 用 boost::regex 代替 linux regex 怎么样?
  • 我只需要最快的方法来做到这一点,所以如果你有什么可以帮助我的想法,请发布答案,以便我可以测试并接受它。
  • 不是windows的吗?
  • 你说最快是指开发时间还是执行速度?

标签: c++ regex linux unix gcc


【解决方案1】:
#include <vector>
#include <string>
#include <boost/regex.hpp>

int main()
{
    boost::regex re(".+-(?<domain>.+)\\s*Logged");
    std::string examples[] = 
    {
        "11-test.domain1.com Logged ...",
        "37-user1.users.domain2.org Logged ..."
    };
    std::vector<std::string> vec(examples, examples + sizeof(examples) / sizeof(*examples));
    std::for_each(vec.begin(), vec.end(), [&re](const std::string& s)
    {
        boost::smatch match;
        if (boost::regex_search(s, match, re))
        {
            std::cout << match["domain"] << std::endl;
        }
    });
}

http://liveworkspace.org/code/1983494e6e9e884b7e539690ebf98eb5 像 boost::regex 这样的东西。不知道pcre。

【讨论】:

  • @KendallHildebrandt 此代码在 gcc4.5+ 中编译并安装了 boost...您可以根据 pcre 重写此代码。
  • 它是否使用 -static 选项编译?
  • @KendallHildebrandt 是的,如果 boost 库是在静态中构建的...而且你应该使用 -std=c++0x flg。
  • @KendallHildebrandt 并尝试为您的代码使用正则表达式... ".+-(.+)\\s*Logged"
【解决方案2】:

是标准格式吗? 好像是这样,有拆分功能吗?

编辑: 这是一些逻辑。 遍历要解析的每个域 找一个函数来定位第一个字符串“-”的索引 接下来找到第二个字符串的索引减去第一个字符串“Logged” 现在您拥有完整的域。

一旦您拥有完整的域,就将域“拆分”为您选择的对象(我使用了一个数组) 现在您已将数组拆分开来,找到您希望重新组合(连接)以仅捕获域的值的索引。

注意用 C# 编写

定义第一个值和第二个值的主方法

`static void Main(string[] args)
        {
            字符串 firstValue ="-";
            字符串 secondValue = "记录";
            列出域 = 新列表 { "11-test.domain1.com Logged", "37-user1.users.domain2.org Logged","48-me.server.domain3.net Logged"};
            foreach(域中的字符串 dns)
            {
                Debug.WriteLine(Utility.GetStringBetweenFirstAndSecond(dns, firstValue, secondValue));
            }
        }
`

解析字符串的方法:

`public string GetStringBetweenFirstAndSecond(string str, string firstStringToFind, string secondStringToFind)
        {
            字符串域 = string.Empty;

            如果(字符串。IsNullOrEmpty(str))
            {
                //抛出异常,优雅返回,无论你决定什么
            }
            别的
            {
                //这一切都可以在一行中完成,但我把它分开了,这样可以更好地理解。
                //返回第一次出现。
                //int start = str.IndexOf(firstStringToFind) + 1;

                //int end = str.IndexOf(secondStringToFind);

                //domain = str.Substring(start, end - start);

                //IE。绝对不是那么清晰,但不会不必要地创建对象
                domain = str.Substring((str.IndexOf(firstStringToFind) + 1), str.IndexOf(secondStringToFind) - (str.IndexOf(firstStringToFind) + 1));

                string[] dArray = domain.Split('.');

                如果(dArray.Length > 0)
                {
                    如果(dArray.Length > 2)
                    {
                        domain = string.Format("{0}.{1}", dArray[dArray.Length - 2], dArray[dArray.Length - 1]);
                    }
                }
            }

            返回域;
        }
`

【讨论】:

  • 每个缓冲区包含一行,它是一个文本文件。我可以得到每一行,但不知道如何提取“-”和“找到”之间的字符串,然后将其拆分以仅提取域
猜你喜欢
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多