为什么 Perl 给出 "Can't modify string in scalar output" 错误?
Why is Perl giving "Can't modify string in scalar output" error?
我是 Perl 的新手,这是我迄今为止最复杂的项目。如果我解释的任何部分没有意义或者我遗漏了什么,我深表歉意 - 我很乐意提供进一步的说明。只有一行代码导致了我的问题。
目标:
我有一个包含单列数据的文本文件。它是这样写的:
0
a,a,b,a
b,b,b,a
1
a,b,b,a
b,b,b,a
这样继续一个数字升序到15,每个数字后面的两行是四个a或b的组合,用逗号分隔。我已将此文件绑定到数组 @diplo
,因此我可以指定其中的特定行。
我还有一个文件,其中包含两列数据 headers 我已将其转换为数组的散列(两列中的每一列都是一个数组)。哈希的名称是 $lookup,数组名称是标题的名称。实际数组仅从每列中不是标题的第一个值开始。该文件如下所示:
haplo frequency
"|5,a,b,a,a|" 0.202493719
"|2,b,b,b,a|" 0.161139191
"|3,b,b,b,a|" 0.132602458
此文件包含 a 或 b 在四个位置的所有可能组合以及所有数字 0-14 及其相关频率。换句话说,它包括来自“|0,a,a,a,a|”的所有可能组合接下来是“|1,a,a,a,a|”一直到“|13,b,b,b,b|”和“|14,b,b,b,b|”。
我希望我的 Perl 代码遍历 @diplo 中以 a,a,b,a 开头的每个字母组合,并记录与包含 0-14 中每个数字的 haplo 数组的行关联的频率,例如首先记录与“|0,a,a,b,a|”相关的频率然后是“|1,a,a,b,a|”等等
输出应该是这样的:
0 #this is the number in the @diplo file and they increase in order from 0 up to 15
0.011 0.0023 0.003 0.0532 0.163 0.3421 0.128 0.0972 0.0869 0.05514 0.0219 0.0172 0.00824 0.00886 0.00196 #these are the frequencies associated with x,a,a,b,a where x is any number from 0 to 14.
我的代码:
这是我创建的 Perl 代码,希望能解决这个问题(如果需要,我可以 post 创建数组,但我不想 post 一大堆代码如果没有必要):
my $irow = 1; #this is the row/element number in @diplo
my $lrow = 0; #this is the row/element in $lookup{'haplo'}
my $copynumber = 0;
#print "$copynumber, $diplo[2]";
while ($irow < $diplolines - 1) {
while ($copynumber < 15) {
while ($lrow < $uplines - 1) {
if ("|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]) { ##this is the only line that causes errors
if ($copynumber == 0) {
print "$diplo[$irow-1]\n";
#print "$lookup{'frequency'}[$lrow]\t";
}
print "$lookup{'frequency'}[$lrow]\t";
}
$lrow = $lrow + 1;
}
$lrow = 0;
$copynumber = $copynumber + 1;
}
$lrow = 0;
$copynumber = 0;
$irow = $irow + 1;
}
但是,行 if ("|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow])
导致错误 Can't modify string in scalar assignment near "]) "
。
我已经尝试在该行的各个元素周围添加语音标记、圆括号和 postrophes,但我仍然对这个错误有某种变体。我不确定如何解决此错误。
很抱歉问题很长,如有任何帮助,我们将不胜感激。
编辑:感谢关于 eq
的建议,它消除了错误,我现在比以前更了解 Perl。但是,即使我现在没有收到错误,如果我将任何内容放入此行的 if
循环中,例如打印一个数字,它不会被执行。如果我在 while
循环内但在 if
外放置相同的命令,它确实会被执行。我有严格和警告。有什么想法吗?
=
是赋值,==
是数值比较,eq
是字符串比较。
您不能修改字符串:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" = "abcdef") { print "match\n"; } '
Found = in conditional, should be == at -e line 1.
Can't modify string in scalar assignment at -e line 1, near ""abcdef") "
Execution of -e aborted due to compilation errors.
非数字字符串在数字比较中就像零:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" == 0) { print "match\n"; } '
Argument "abcdef" isn't numeric in numeric eq (==) at -e line 1.
match
字符串比较可能就是你想要的:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" eq "abcdef") { print "match\n"; } '
match
这是有问题的表达式:
"|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]
等号 (=
) 是赋值运算符。它将右侧的值分配给左侧的变量。因此,左边的操作数需要是一个变量,而不是这里的字符串。
我认为你根本不想在这里做作业。我认为您正在尝试检查是否相等。所以不要使用赋值运算符,使用比较运算符。
Perl 有两个相等比较运算符。 ==
进行数字比较以查看其操作数是否相等,eq
进行字符串比较。为什么 Perl 需要两个运算符? Perl 会自动在字符串和数字之间进行转换,因此它不可能知道您想要进行哪种比较。所以你需要告诉它。
这两种比较有什么区别?好吧,考虑一下这段代码。
$x = '0';
$y = '0.0';
$x
和 $y
相等吗?好吧,这取决于您进行的比较类型。如果将它们作为数字进行比较,那么,是的,它们是相同的值(无论是整数还是实数,零都是一样的)。但是如果你将它们作为字符串进行比较,它们是不同的(它们的长度一开始就不一样)。
所以我们现在知道以下内容
$x == $y # this is true as it's a numeric comparison
$x eq $y # this is false as it's a string comparison
那么让我们回到您的代码:
"|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]
我猜你从这里开始 ==
。
"|$copynumber,$diplo[$irow]|" == $lookup{'haplo'}[$lrow]
但这不对,因为 |$copynumber,$diplo[$irow]|
显然是字符串,而不是数字。如果您尝试使用看起来不像数字的值进行数字比较,Perl 会给您一个警告。
因此您将其更改为 =
,但这也不起作用,因为您现在已将其更改为作业。
你真正需要的是字符串比较:
"|$copynumber,$diplo[$irow]|" eq $lookup{'haplo'}[$lrow]
我是 Perl 的新手,这是我迄今为止最复杂的项目。如果我解释的任何部分没有意义或者我遗漏了什么,我深表歉意 - 我很乐意提供进一步的说明。只有一行代码导致了我的问题。
目标:
我有一个包含单列数据的文本文件。它是这样写的:
0
a,a,b,a
b,b,b,a
1
a,b,b,a
b,b,b,a
这样继续一个数字升序到15,每个数字后面的两行是四个a或b的组合,用逗号分隔。我已将此文件绑定到数组 @diplo
,因此我可以指定其中的特定行。
我还有一个文件,其中包含两列数据 headers 我已将其转换为数组的散列(两列中的每一列都是一个数组)。哈希的名称是 $lookup,数组名称是标题的名称。实际数组仅从每列中不是标题的第一个值开始。该文件如下所示:
haplo frequency
"|5,a,b,a,a|" 0.202493719
"|2,b,b,b,a|" 0.161139191
"|3,b,b,b,a|" 0.132602458
此文件包含 a 或 b 在四个位置的所有可能组合以及所有数字 0-14 及其相关频率。换句话说,它包括来自“|0,a,a,a,a|”的所有可能组合接下来是“|1,a,a,a,a|”一直到“|13,b,b,b,b|”和“|14,b,b,b,b|”。
我希望我的 Perl 代码遍历 @diplo 中以 a,a,b,a 开头的每个字母组合,并记录与包含 0-14 中每个数字的 haplo 数组的行关联的频率,例如首先记录与“|0,a,a,b,a|”相关的频率然后是“|1,a,a,b,a|”等等
输出应该是这样的:
0 #this is the number in the @diplo file and they increase in order from 0 up to 15
0.011 0.0023 0.003 0.0532 0.163 0.3421 0.128 0.0972 0.0869 0.05514 0.0219 0.0172 0.00824 0.00886 0.00196 #these are the frequencies associated with x,a,a,b,a where x is any number from 0 to 14.
我的代码: 这是我创建的 Perl 代码,希望能解决这个问题(如果需要,我可以 post 创建数组,但我不想 post 一大堆代码如果没有必要):
my $irow = 1; #this is the row/element number in @diplo
my $lrow = 0; #this is the row/element in $lookup{'haplo'}
my $copynumber = 0;
#print "$copynumber, $diplo[2]";
while ($irow < $diplolines - 1) {
while ($copynumber < 15) {
while ($lrow < $uplines - 1) {
if ("|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]) { ##this is the only line that causes errors
if ($copynumber == 0) {
print "$diplo[$irow-1]\n";
#print "$lookup{'frequency'}[$lrow]\t";
}
print "$lookup{'frequency'}[$lrow]\t";
}
$lrow = $lrow + 1;
}
$lrow = 0;
$copynumber = $copynumber + 1;
}
$lrow = 0;
$copynumber = 0;
$irow = $irow + 1;
}
但是,行 if ("|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow])
导致错误 Can't modify string in scalar assignment near "]) "
。
我已经尝试在该行的各个元素周围添加语音标记、圆括号和 postrophes,但我仍然对这个错误有某种变体。我不确定如何解决此错误。
很抱歉问题很长,如有任何帮助,我们将不胜感激。
编辑:感谢关于 eq
的建议,它消除了错误,我现在比以前更了解 Perl。但是,即使我现在没有收到错误,如果我将任何内容放入此行的 if
循环中,例如打印一个数字,它不会被执行。如果我在 while
循环内但在 if
外放置相同的命令,它确实会被执行。我有严格和警告。有什么想法吗?
=
是赋值,==
是数值比较,eq
是字符串比较。
您不能修改字符串:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" = "abcdef") { print "match\n"; } '
Found = in conditional, should be == at -e line 1.
Can't modify string in scalar assignment at -e line 1, near ""abcdef") "
Execution of -e aborted due to compilation errors.
非数字字符串在数字比较中就像零:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" == 0) { print "match\n"; } '
Argument "abcdef" isn't numeric in numeric eq (==) at -e line 1.
match
字符串比较可能就是你想要的:
$ perl -e 'use strict; use warnings; my $foo="def";
if ("abc$foo" eq "abcdef") { print "match\n"; } '
match
这是有问题的表达式:
"|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]
等号 (=
) 是赋值运算符。它将右侧的值分配给左侧的变量。因此,左边的操作数需要是一个变量,而不是这里的字符串。
我认为你根本不想在这里做作业。我认为您正在尝试检查是否相等。所以不要使用赋值运算符,使用比较运算符。
Perl 有两个相等比较运算符。 ==
进行数字比较以查看其操作数是否相等,eq
进行字符串比较。为什么 Perl 需要两个运算符? Perl 会自动在字符串和数字之间进行转换,因此它不可能知道您想要进行哪种比较。所以你需要告诉它。
这两种比较有什么区别?好吧,考虑一下这段代码。
$x = '0';
$y = '0.0';
$x
和 $y
相等吗?好吧,这取决于您进行的比较类型。如果将它们作为数字进行比较,那么,是的,它们是相同的值(无论是整数还是实数,零都是一样的)。但是如果你将它们作为字符串进行比较,它们是不同的(它们的长度一开始就不一样)。
所以我们现在知道以下内容
$x == $y # this is true as it's a numeric comparison
$x eq $y # this is false as it's a string comparison
那么让我们回到您的代码:
"|$copynumber,$diplo[$irow]|" = $lookup{'haplo'}[$lrow]
我猜你从这里开始 ==
。
"|$copynumber,$diplo[$irow]|" == $lookup{'haplo'}[$lrow]
但这不对,因为 |$copynumber,$diplo[$irow]|
显然是字符串,而不是数字。如果您尝试使用看起来不像数字的值进行数字比较,Perl 会给您一个警告。
因此您将其更改为 =
,但这也不起作用,因为您现在已将其更改为作业。
你真正需要的是字符串比较:
"|$copynumber,$diplo[$irow]|" eq $lookup{'haplo'}[$lrow]