Regex 调试perl赋值

Regex 调试perl赋值,regex,perl,Regex,Perl,我应该解释一下,作为这个问题的背景,我不懂任何Perl,并且对正则表达式非常敏感 (我们都有自己的弱点)。我试图弄明白为什么Perl程序不接受我提供给它的数据。我不需要深入理解这个程序——我只是在做一个时间比较 请考虑以下分配声明: ($sample_ls_id) = $sample_ls_id =~ /:\w\w(\d+):/; 如果我理解正确,它将检查sample\ls\u id是否匹配某个正则表达式,如果匹配,则分配整个字符串,或者类似的内容 然而,我不明白这是怎么回事。 根据文件,也就

我应该解释一下,作为这个问题的背景,我不懂任何Perl,并且对正则表达式非常敏感 (我们都有自己的弱点)。我试图弄明白为什么Perl程序不接受我提供给它的数据。我不需要深入理解这个程序——我只是在做一个时间比较

请考虑以下分配声明:

($sample_ls_id) = $sample_ls_id =~ /:\w\w(\d+):/;
如果我理解正确,它将检查
sample\ls\u id
是否匹配某个正则表达式,如果匹配,则分配整个字符串,或者类似的内容

然而,我不明白这是怎么回事。 根据文件,也就是我简单地看了一下

$sample_ls_id =~ /:\w\w(\d+):/
如果存在匹配项,则仅返回true或false

我要匹配的字符串看起来像

1000    10      0       0       1        urn:lsid:dcc.hapmap.org:Individual:CEPH1000.10:1        urn:lsid:dcc.hapmap.org:Sample:SAMPLE1:1
此操作失败并出现错误

Use of uninitialized value $sample_ls_id in concatenation (.) or string
at database/populate/family.pl line 38, <INPUT> line 1.
请参阅下面的完整脚本。然而,显然非常相似的字符串

1420    9       0       0       1       urn:lsid:dcc.hapmap.org:Individual:CEPH1420.09:1  urn:lsid:dcc.hapmap.org:Sample:NA12003:1
似乎过去了

对于上下文,整个代码段是:

use strict;
use warnings;
use Getopt::Long;

my $input_file = "data/family_ceu.txt";
my $output_file = "sql/family_ceu.sql";
my $population_code = "CEU";

GetOptions ('i=s' => \$input_file,
            'o=s' => \$output_file,
            'p=s' => \$population_code
            );

usagecheck();

my $created_by = 'gwas_analyzer';

print "Creating SQL file for inserting family data from $input_file\n";

open (INPUT, "< $input_file");
open (OUTPUT, "> $output_file");

print OUTPUT "INSERT INTO population (population_code, private) VALUES ('$population_code', 'f');\n";
print OUTPUT "COPY family (ls_id, family_ped_id, individual_ped_id, father_ped_id, mother_ped_id, sex, created_by, population_code) FROM stdin;                      
";

while (my $line = <INPUT>)
{
    chomp $line;

    #Skip any comment lines 
    next if($line =~ /^#/);

    my ($family_ped_id, $individual_ped_id, $father_ped_id, $mother_ped_id, $sex, $individual_ls_id, $sample_ls_id) = split (/\t/, $line);

    ($sample_ls_id) = $sample_ls_id =~ /:\w\w(\d+):/;

    print OUTPUT "$sample_ls_id\t$family_ped_id\t$individual_ped_id\t$father_ped_id\t$mother_ped_id\t$sex\t$created_by\t$population_code\n";
}

print OUTPUT "\\.\n";
close OUTPUT;

sub usagecheck
{
    if (!$input_file || !$output_file || !$population_code)
    {
        print "Missing argument (see required arguments below):\n";
        usage();
        exit;
    }
}

sub usage
{
    print "perl family.pl -i <input file> -o <output file> -p <population code>\n";
}
使用严格;
使用警告;
使用Getopt::Long;
my$input_file=“data/family_ceu.txt”;
my$output\u file=“sql/family\u ceu.sql”;
我的$population\u code=“CEU”;
GetOptions('i=s'=>\$input\u文件,
'o=s'=>\$output\u文件,
'p=s'=>\$population\u代码
);
usagecheck();
my$created_by='gwas_analyzer';
打印“创建用于从$input\u文件插入族数据的SQL文件\n”;
打开(输入“<$INPUT_文件”);
打开(输出“>$OUTPUT_文件”);
打印输出“插入填充(填充代码,专用)值(“$population\u code”,“f”);\n”;
打印输出“从stdin复制家庭(家庭id、家庭id、个人id、父亲id、母亲id、性别、创建人、人口代码);
";
while(我的$line=)
{
chomp$行;
#跳过任何注释行
下一个if($line=~/^#/);
我的($family\u ped\u id、$individual\u ped\u id、$father\u ped\u id、$sex、$individual\u ls\u id、$sample\u ls\u id)=拆分(/\t/,$line);
($sample\u ls\u id)=$sample\u ls\u id=~/:\w\w(\d+):/;
打印输出“$sample\u ls\u id\t$family\u ped\u id\t$individual\u ped\u id\t$father\u ped\u id\t$mother\u ped\u id\t$sex\t$created\t$population\u code\n”;
}
打印输出“\\.\n”;
闭合输出;
子用途检查
{
if(!$input_file | |!$output_file |!$population_code)
{
打印“缺少参数(请参见下面的必需参数):\n”;
用法();
出口
}
}
次级用途
{
打印“perl family.pl-i-o-p\n”;
}

如果您了解正则表达式和Perl,我相信这是一个非常简单的问题。

与其将字符串本身存储起来,不如使用捕获。 \d由1美元持有,因此只需将代码更改为如下内容:

$sample_ls_id =~ /:\w\w(\d+):/; # no letters before implies "match"
$sample_ls_id = $1; # I assume that $1 will be empty if no match, I'm not 100% on this.
我不知道为什么会出现这样的错误,但看起来你的代码会像上面那样更有意义

如果您的输入没有最后一个元素(即,您有A:B:C,但您需要A:B:C:D将D存储在示例ls id中,如果D丢失,则它永远不会初始化,并且正则表达式没有意义),那么这可能与此有关


此外,如果您发布更多可能有用的内容,我们也没有所有代码(第38行看起来与while循环中的第一行相对应)。

在列表上下文中,例如分配给
($sample\ls\u id)
=~
返回捕获列表。它可以在一个单独的语句中节省提取
$1
等的时间。

$sample\u ls\u id='urn:lsid:dcc.hapmap.org:sample:SAMPLE1:1'时

正则表达式“/:\w\w(\d+):/;”失败。当字符串后面有冒号“:”和“word”字符“\w”时,此正则表达式将传递, 另一个“单词”字符“\w”,后跟一个或多个数字“\d+”和冒号“:”


$sample_ls_id='urn:lsid:dcc.hapmap.org:sample:NA12003:1'时

正则表达式“/:\w\w(\d+):/;”在中找到匹配项 “:NA12003:”。(冒号,2个单词字符,数字和冒号)

“($sample_ls_id)”捕获匹配的“(\d+”部分(也存储在$1中),在本例中为12003


您在前面的示例中遇到了一个错误,因为正则表达式失败并且未定义“($sample_ls_id)”。

sample_ls_id的目标是什么?您只是想捕获\d+并将其存储在示例\u ls\u id中吗?如果没有匹配项,您希望样本id保存什么?@onaclov2000:我想是的。它最终会写入一个文件。嗯,不是我,而是这段代码的作者。:-)您正在拆分制表符,但是示例输入没有制表符分隔,因此这有点混乱,您可以更新吗?我的示例输入不是要拆分的整行,只是最后一个元素。我将发布整行内容。谢谢,我以前没有这样做过,我想知道问题是否出在正则表达式上……错误指向正则表达式之前的某个地方,它看起来像是在列表上下文中,当有捕获括号时。如果没有,则返回()或1表示成功或失败。确定。如果有帮助的话,我可以发布整个有问题的Perl脚本。我不是这段代码的作者,我只是想弄明白它的意思。我不知道任何Perl。你在这一点上100%错了:-)$1将包含一些以前成功匹配的过时剩余值。“除非您首先测试匹配成功,否则不应使用美元数字变量”。如果匹配失败,您将插入一个难以找到的bug。原始构造(列表上下文中的匹配)是避免此问题的一种方法。如果匹配失败,那么它将返回空列表,$sample_ls_id将包含undf因此,我没有在该上下文之外使用$1。我以后必须记住这一点!我明白了。所以问题是,我在本例中的字符串
SAMPLE
不是两个字符长?这很可笑,但我没有编写此代码。我希望确认我的理解是正确的。谢谢。是的,没错。我f你
$sample_ls_id =~ /:\w\w(\d+):/; # no letters before implies "match"
$sample_ls_id = $1; # I assume that $1 will be empty if no match, I'm not 100% on this.
my $sample_id = 'urn:lsid:dcc.hapmap.org:Sample:NA12003:1'
($sample_ls_id) = $sample_ls_id =~ /:\w\w(\d+):/;