perl踩坑系列之foreach

发布时间:2026/9/25 21:49:35
perl踩坑系列之foreach 先上代码#!/usr/bin/perl -w use strict; use Cwd realpath; use File::Basename; use FindBin qw($Bin $Script); use Getopt::Long; use Storable; use lib /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab; use Common; my $common Common - new(); $| 1; my ($group,$key,$run_type,$run, $rm_temp,$show_prerequisites,$check_before_run, $num); my rm_downstream; my $rm_self_log; my $rm_all_log; my $specific_shell; my $wait; my exclude_nodes (); #exclude_nodes (cn16, cn17); exclude_nodes (cn16); print test_0.(join , exclude_nodes).\n; GetOptions( groups \$group, keys \$key, run_types \$run_type, rm_temp! \$rm_temp, show_prerequisites! \$show_prerequisites, run! \$run, numi \$num, check_before_run! \$check_before_run, rm_downstreams \rm_downstream, rm_self_log! \$rm_self_log, rm_all_log! \$rm_all_log, specific_shells \$specific_shell, exclude_nodess \exclude_nodes, waiti \$wait ); my %PipeLine; $group genelab.q,bigmem; my $count 0; foreach my $sh(ARGV){ $count ; $PipeLine{cpu}{$sh} 2; $PipeLine{memory}{$sh} 20G; qsub_sge($sh); print test_$count.(join , exclude_nodes).\n; } #以下是正常跑流程 sub get_exclude_nodes{ my node_tmp (); foreach my $node(_) { #print test_1$node\n; if ($node !~ /\.local/) {$node . .local;} $node h!$node; push(node_tmp, $node); } my $exclude join , node_tmp; return $exclude; } sub qsub_sge{ my $sh shift; my $date date %Y-%m-%d%t%H:%M:%S;chomp($date); my $cmd qsub -cwd -V -q $group; #$group 一般是genelab.q 但也可以写成 genelab.q,bigmem,herb.q 之类的 if(scalar(exclude_nodes) 0){ my $exclude get_exclude_nodes(exclude_nodes); #qsub -q herb.q,default.q -l h_vmem10G -l h!cn22.localh!cn23.local job.sh $cmd . -l \$exclude\ ; } if (exists $PipeLine{cpu}{$sh}){$cmd . -pe smp $PipeLine{cpu}{$sh};} if (exists $PipeLine{hostname}{$sh}){ $cmd . -l hostname$PipeLine{hostname}{$sh}; if(exists $PipeLine{serve_fa_for}{$sh}){ $cmd . -l h_vmem$PipeLine{memory}{$sh} -e $sh.$PipeLine{hostname}{$sh}.e -o $sh.$PipeLine{hostname}{$sh}.o $sh; }else{ $cmd . -l h_vmem$PipeLine{memory}{$sh} -e $sh.e -o $sh.o $sh; } }else{ $cmd . -l h_vmem$PipeLine{memory}{$sh} -e $sh.e -o $sh.o $sh; } #print $cmd; $common - print_time($cmd); #print qsub -cwd -V -q $group -pe smp $cpu -l h_vmem$mem -e $sh.e -o $sh.o $sh; }上述是我的的一个流程控制脚本的一部分 取名为control_pipeLine_test.pl运行一下perl /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab/runTumor/control_pipeLine_test.pl a.sh b.sh c.sh运行结果test_0cn16Thu Sep 24 00:06:35 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.local -pe smp 2 -l h_vmem20G -e a.sh.e -o a.sh.o a.shtest_1h!cn16.localThu Sep 24 00:06:35 2026: qsub -cwd -V -q genelab.q,bigmem -l h!h!cn16.local -pe smp 2 -l h_vmem20G -e b.sh.e -o b.sh.o b.shtest_2h!h!cn16.localThu Sep 24 00:06:35 2026: qsub -cwd -V -q genelab.q,bigmem -l h!h!h!cn16.local -pe smp 2 -l h_vmem20G -e c.sh.e -o c.sh.o c.shtest_3h!h!h!cn16.local也就是说 exclude_nodes中元素的内容一直在变。问题出在get_exclude_nodes这个函数的foreach my $node(_)这里。对于foreach my $node(_)而言 $node只是_里面各个元素的别名 在foreach循环里面如果再修改$node那么_中对应元素的值也会跟着变。这跟_其实没关系 A, B也一样比如#!/usr/bin/perl -w use strict; use Cwd realpath; use File::Basename; use FindBin qw($Bin $Script); use Getopt::Long; use Storable; use lib /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab; use Common; my $common Common - new(); my aaa qw(1 33 66); print before: .(join , aaa).\n; foreach my $a(aaa){ $a 3; } print after: .(join , aaa).\n;运行一下脚本得到结果$perl a.pl before: 13366 after: 43669foreach my $node(XXX){}循环中 不能对$node做修改。如果修改了 那么每修改一次XXX中对应元素也跟着修改一次这通常是不合理的。所以get_exclude_nodes函数中的循环应该改一下。修改方式1避免对数组的元素别名进行修改sub get_exclude_nodes{ my node_tmp (); foreach my $node(_) { #print test_1$node\n; if ($node !~ /\.local/) {$node . .local;} #$node h!$node; my $exclude_info h!$node; push(node_tmp, $exclude_info); } my $exclude join , node_tmp; return $exclude; }测试一下$perl /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab/runTumor/control_pipeLine_test.pl a.sh b.sh c.sh test_0cn16cn17 Thu Sep 24 00:20:16 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e a.sh.e -o a.sh.o a.sh test_1cn16.localcn17.local Thu Sep 24 00:20:16 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e b.sh.e -o b.sh.o b.sh test_2cn16.localcn17.local Thu Sep 24 00:20:16 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e c.sh.e -o c.sh.o c.sh test_3cn16.localcn17.local修改方式2 直接将数组复制一份这样虽然对复制后的数组进行了修改 但原数组不受影响。sub get_exclude_nodes_2{ my exclude_info _; #拷贝一份就跟_, 也即主程序的实参exclude_info无关了 my node_tmp (); foreach my $node(exclude_info) { if ($node !~ /\.local/) {$node . .local;} $node h!$node; #此时对 $node操作也不会影响_ push(node_tmp, $node); } my $exclude join , node_tmp; return $exclude; }运行一下$perl /mnt/lustre/user/wubin/01.Program/Scripts/01.script/GeneLab/runTumor/control_pipeLine_test.pl a.sh b.sh c.sh test_0cn16cn17 Thu Sep 24 00:24:22 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e a.sh.e -o a.sh.o a.sh test_1cn16cn17 Thu Sep 24 00:24:22 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e b.sh.e -o b.sh.o b.sh test_2cn16cn17 Thu Sep 24 00:24:22 2026: qsub -cwd -V -q genelab.q,bigmem -l h!cn16.localh!cn17.local -pe smp 2 -l h_vmem20G -e c.sh.e -o c.sh.o c.sh test_3cn16cn17但还是尽量不要对foreach my $node(exclude_info)中的$node进行修改这是一种不好的习惯。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询