-1

编辑更简洁,见谅。

我需要能够使用可能包含以下字符之一的字符串从数组中 grep:'.'、'+'、'/'、'-'。该字符串将通过用户捕获。该数组包含我正在搜索的文件的每一行(我将文件放入数组中以避免在用户与程序交互时保持打开状态,因为它位于 cron 上,我不想拥有它cron 运行时打开),并且每一行都有一个唯一标识符,这是正则表达式中使用的搜索字符串的基础。下面的代码显示了我正在使用的 grep 语句,我在我的程序中使用 OUR 和 MY 来使我想在所有命名空间中访问的变量都可用,而我只在子例程中使用的变量不可用。如果您确实想尝试复制该问题

#!/usr/bin/perl -w

use strict;
use Switch;
use Data::Dumper;

our $pgm_path = "/tmp/";
our $device_info = "";

our @new_filetype1 = ();
our @new_filetype2 = ();
our @dev_info = ();
our @pgm_files = ();

our %arch_rtgs = ();

our $file = "/path/file.csv";
open my $fh, '<', $file or die "Couldn't open $file!\n";
chomp(our @source_file = <$fh>);
close $fh;

print "Please enter the device name:\n";
chomp(our $dev = <STDIN>);

while ($device_info eq "") {
    # Grep the device info from the sms file
    my @sms_device = grep(/\Q$dev\E/, @source_file);
    if (scalar(@sms_device) > 1) {
        my $which_dup = find_the_duplicate(\@sms_device);
        if ($which_dup eq "program") {
            print "\n-> $sms_dev <- must be a program name instead of a device name." .
            "\nChoose the device from the list you are working on, specifically.\n";
            foreach my $fix(@sms_device) {
                my @fix_array = split(',', $fix);
                print "$fix_array[1]\n";
                undef @fix_array;
            }
            chomp($sms_dev = <STDIN>);
            } else { $device_info = $which_dup; }
        } elsif (scalar(@sms_device) == 1) { 
            ($device_info) = @sms_device;
            @sms_device = ();
        }
}

当我尝试使用锚点的代码时:

my @sms_device = grep(/\Q$dev\E^/, @source_file);

没有注意到该程序的更多活动。它只是坐在那里,就像在等待用户的更多输入一样。这不是我所期望的。我想锚定搜索模式的原因是因为有很多类似命名设备的示例具有与搜索模式相同的字符顺序,但还包括在正则表达式评估中被忽略的其他字符。我不希望它们被忽略,因为它们包含在匹配项中。我想强制变量中的字符串完全匹配。

提前感谢您通过我非常缺乏经验的代码和沟通尝试来详细说明我的问题。

4

2 回答 2

1

设备 id 后跟字符串的开头?/\Q$dev\E^/没有意义。您希望设备 id 前面是字符串的开头,后面是字符串的结尾。

grep { /^\Q$dev\E\z/ }

更好的是,让我们避免白白启动正则表达式引擎。

grep { $_ eq $dev }

例如,

$ perl -e'my $dev = "ccc"; CORE::say for grep { /^\Q$dev\E\z/ } qw( accc ccc ccce );'
ccc

$ perl -e'my $dev = "ccc"; CORE::say for grep { $_ eq $dev } qw( accc ccc ccce );'
ccc
于 2018-12-19T19:58:51.523 回答
0

我会用quotemeta. 以下是它如何比较的示例:

my $regexp = '\t';
my $metaxp = quotemeta ($regexp);

while (<DATA>) {
  print "match \$regexp - $_" if /$regexp/;
  print "match \$metaxp - $_" if /$metaxp/;
}

__DATA__
This \t is not a tab
This    is a tab

(实际上第二行有一个标签)

元版本将匹配第 1 行,因为它将“\t”本质上变成了“\t”,而非元(原始)版本将匹配第 2 行,假设您正在寻找一个选项卡。

match $metaxp - This \t is not a tab
match $regexp - This    is a tab

希望你明白我的意思。

我认为添加$regexp = quotemeta ($regexp)(或在捕获标准输入时添加)应该可以满足您的需要。

于 2018-12-19T18:47:33.817 回答