修改Perl代码适配多输入文件,实现GNU Makefile自动测试
问题:修改Perl脚本支持指定输入文件,配合Makefile批量测试
现有场景与需求
当前开发项目需用GNU Makefile自动测试Perl程序,测试时要处理不同输入文件。现有Perl脚本仅能读取固定路径的单个输入文件,识别停用词后将非停用词频率表输出到固定路径的out.txt,代码如下:
#!/usr/bin/perl use strict; use warnings; use Lingua::StopWords qw(getStopWords); my %found; my $src = '/programu-testavimas/1-dk/trunk/tests/inputs/test.txt'; my $des = '/programu-testavimas/1-dk/trunk/tests/outputs/out.txt'; open(SRC,'<',$src) or die $!; open(DES,'>',$des) or die $!; my $stopwords = getStopWords('en'); while( my $line = <SRC> ){ ++$found{$_} for grep { !$stopwords->{$_} } split /\s+/, lc $line; } print DES $_, "\t\t", $found{$_}, $/ for sort keys %found; close(SRC); close(DES);
目标是通过独立的case.sh脚本为每个测试用例指定不同输入文件,再用Makefile批量执行所有测试用例。现有一个测试用例脚本示例:
#!/bin/sh perl /programu-testavimas/1-dk/trunk/scripts/test.pl /programu-testavimas/1-dk/trunk/tests/inputs/test.txt > /home/aleksandra/programų-testavimas/1-dk/trunk/tests/outputs/out.txt
曾尝试用glob修改Perl代码,但输出文件为空,修改后的代码片段如下:
open(DES,'>',$des) or die $!; my $stopwords = getStopWords('en'); for my $file ( glob $src ) { open(SRC,'<',$file) or die "$! opening $file"; while( my $line = <SRC> ){ ++$found{$_} for grep { !$stopwords->{$_} } split /\s+/, lc $line; } print DES $_, "\t\t", $found{$_}, $/ for sort keys %found; close(SRC); } close(DES);
解决方案
1. 修改Perl脚本支持命令行参数
将固定的输入/输出路径改为从命令行参数读取,这样每个测试用例可以独立指定文件路径,代码修改如下:
#!/usr/bin/perl use strict; use warnings; use Lingua::StopWords qw(getStopWords); # 从命令行获取输入、输出文件路径,缺少参数时提示用法 my ($input_file, $output_file) = @ARGV; die "用法: $0 <输入文件路径> <输出文件路径>" unless defined $input_file && defined $output_file; my %word_counts; my $stopwords = getStopWords('en'); # 打开输入文件并处理内容 open(my $src_fh, '<', $input_file) or die "打开输入文件失败 $input_file: $!"; while (my $line = <$src_fh>) { # 拆分单词、转小写、过滤停用词后统计频率 ++$word_counts{$_} for grep { !$stopwords->{$_} } split /\s+/, lc $line; } close($src_fh); # 将统计结果写入输出文件 open(my $des_fh, '>', $output_file) or die "打开输出文件失败 $output_file: $!"; print $des_fh "$_\t\t$word_counts{$_}\n" for sort keys %word_counts; close($des_fh);
2. 更新测试用例脚本case.sh
修改脚本直接向Perl脚本传递输入、输出文件参数,无需依赖重定向:
#!/bin/sh PERL_SCRIPT="/programu-testavimas/1-dk/trunk/scripts/test.pl" INPUT="/programu-testavimas/1-dk/trunk/tests/inputs/test.txt" OUTPUT="/home/aleksandra/programų-testavimas/1-dk/trunk/tests/outputs/out.txt" $PERL_SCRIPT "$INPUT" "$OUTPUT"
3. 编写Makefile批量执行测试
假设所有测试用例脚本放在tests/cases/目录下,Makefile内容如下:
# 匹配所有测试用例脚本 TEST_CASES := $(wildcard tests/cases/*.sh) # 默认目标:运行全部测试 all: $(TEST_CASES) # 单个测试用例的执行规则 $(TEST_CASES): @echo "执行测试用例: $@" @chmod +x $@ @$@ # 清理所有输出文件(可选) clean: rm -f tests/outputs/*.txt
原修改失败原因
- 原代码中
$src是固定单个文件路径,glob无法匹配多个文件,导致循环未执行; - 即使匹配到文件,每次循环都会打印一次频率表,造成重复输出;
- 使用全局文件句柄
SRC、DES存在风险,词法文件句柄(my $fh)更安全可靠。
内容的提问来源于stack exchange,提问作者cinnamond
相关产品推荐
相关产品推荐

