【问题标题】:Perl: index() won't work with variable like $array[$i] [closed]Perl:index() 不能与 $array[$i] [关闭] 之类的变量一起使用
【发布时间】:2021-01-24 18:22:12
【问题描述】:

我有两个数组,一个包含来自错误日志的长字符串,另一个包含单词列表。我需要查找,其中一个词是否与任何错误字符串匹配。我想使用 index()。

我拥有的是: @park 是一整页,一行一行。我剪下第 1 行并将其放入 $err1 @omit 是从文件中读取的单词列表。包含“Kein Zugriffsrecht”、“违反约束”等。我从一个数组中逐行获取(用chomp()处理)并将其放入$fehler。

while (@park){
    my $i = $#park;
    $zeile1 = splice (@park,$i,1);
    @foo1 = split(";", $zeile1);
    $err1 = $foo1[1];
    
    for my $b (0..$#omit){
    $prob1 = 0;
    $fehler = $omit[$b];
#   $fehler="constraint violation";

    $prob1 = index ($err1, $fehler);
...
}   

重点是,$prob1 = index ($err1, $fehler); 总是 给出 -1(未找到)。如果我将$fehler 设置为“违反约束”之类的东西,就像上面注释的行一样,index() 将给出正确的数字。 什么可能导致这种行为? 问候

【问题讨论】:

  • 我的代码一半是德语,一半是英语,我会发疯的。你如何设法不把东西混在一起?特别是$err1$fehler。如果你在 $work 上把它交给我来审查,我们可能会在周五下午进行不愉快的聊天。 - 说真的,欢迎来到 Stack Overflow。请花点时间阅读How to Ask 并提供minimal reproducible example。本质上,请edit 您的问题并为@park@omit 提供一些示例数据。谢谢! :)
  • @omit 的元素是否有尾随换行符? (即,你有没有打电话给index($err1,"constraint violation\n")?)
  • 你远远领先于你应该达到的位置。 “我想使用 index()”是你做错了什么的明确信号。 (因为没有人真正想要使用索引)备份 10 步然后寻求帮助。
  • @TLP 绝对可以与那种情绪相关,但如果他们真的想要只是子字符串的索引,那么index 就是工具(并且比启动正则表达式引擎快得多)
  • 如果你能提供一些样本数据——很少会做——那么我们就能弄清楚为什么index会失败

标签: arrays perl string-matching


【解决方案1】:

总的来说,问题中的方法很好,详细信息如下。我不知道您为什么在这里特别“想要使用 index()”,但是如果您确实 想要找到子字符串的索引,那很好。我提供了一个更灵活的替代方案(正则表达式)。

while (@park) {
    my $zeile1 = pop @park;
    my @foo1 = split(";", $zeile1);
    my $err1 = $foo1[0];
    
    for my $b (0..$#omit) {
        my $prob1 = 0;
        my $fehler = $omit[$b];

        if ($err1 =~ /$fehler/) { 
            $prob1 = $-[0];     # position of last match's start
            ...
        }
        ...
     }
} 

这会尝试从您的代码中保留详细信息。有关进一步的简化,请参见下文。关于问题中发布的代码的一些注释:

  • splice 用于移除并返回最后一个字符;为此使用pop

  • $foo1[1]second 项目,而不是所述的第一个项目;固定

  • 我不知道为什么你的index 不起作用;也许@omit 不包含您认为的内容?我使用了另一种方法(正则表达式),你可以用它做更多的事情。但是,如果您实际上只需要匹配的位置,那么请修复 index

  • @omit 上的循环超出了它的索引。如果您不进一步使用该索引,则没有理由涉及它;循环遍历元素

    foreach my $error (@omit) {
        my $prob1 = 0;
    
        if ($err1 =~ /$error/) { 
            $prob1 = $-[0];    # position of last match's start
            ...
        }
        ...
    }
    

    (为了语言的一致性,我把 fehler 改成了英文)

  • 循环顶部也可以简化

    while (my $row1 = pop @park) { 
        my @foo1 = split /;/, $row1;
        ...
    } 
    

    我更改了split 参数的分隔符,以提醒它是一个正则表达式。为了保持一致性,我将 zeile 更改为英文(“row”)

  • 很少在代码中声明任何内容;也许您在更高的范围内声明?在尽可能紧凑的范围内声明变量是有益的。未在循环外使用的变量应在分配时正确声明

  • 混合使用变量名的语言会让你发疯,让读者感到痛苦(特别是如果他们两种语言都说得不够好)。两者都可能直接导致错误。为什么不选择一种语言来始终如一地使用?

可能还可以进行进一步的简化和清理,但我们不知道代码后面会发生什么

  • @foo1 用得更多吗?如果是,您是否希望每次都删除它的前面元素 (shift)?

  • @omit是怎么处理的,$prob1有什么用?可以在一个语句中完成所有这些(可能涉及map),简洁可能有助于提高可读性

  • 一些典型的数据是什么样的?这可以很好地解释为什么 index 找不到子字符串

【讨论】:

  • 首先非常感谢你们所有的cmets!
  • “我想使用 index()”的原因是,我只需要知道 $err1 是否包含我的字符串 $fehler。如果不是,请执行某些操作,如果是,请转到下一个 $err1 条目。最终,我找到了 index() 不起作用的原因:包含搜索短语的文本文件有 windows 行结尾!所以 chomp 确实删除了 \n,但原因是没有删除 \r,这导致了错误。如果我的问题不恰当,我想道歉——我喜欢 perl,但我绝不是 perl 的传道者。下次我会更精确,我保证!
  • @agri 啊,windows 行尾——一个常见的罪魁祸首!很好的发现。如果您只想知道字符串中是否包含某些内容,那么正则表达式最能反映该意图;与index 我认为您需要实际位置。 (当然你可以使用index,只是它可能会误导读者——包括你自己几个月后忘记了写的那段代码,更不用说代码的作用了。:) 除非“做某事”涉及索引,在这种情况下,index 在我看来是最好的工具。
  • @agri 我觉得你的问题是合理的,虽然可能有点笨拙;不过没关系,写一个好问题并不容易,这是你的第一个。我真的不明白为什么它两次得到-1并被关闭。所以不要为此感到难过,只是写下一个更好:)。显然缺少的一件事是一些样本数据。 总是显示一些数据 :)(好吧,如果可能的话。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2015-09-11
  • 2021-12-19
  • 2012-01-03
相关资源
最近更新 更多