Perl脚本A替换脚本B数组时匹配异常及数组标识未修改问题求助
Let's break down why your current approach isn't working and fix it properly:
What's Wrong with Your Current Code?
You're hitting three key issues that are causing unintended behavior:
Unresolved Variable in Shell Command
Yourperl -pi -ecommand is wrapped in single quotes, which means the$listvariable from Script A never gets expanded by your main Perl process—it’s treated as a literal, undefined variable in the one-off Perl instance you’re spawning. That’s why your new array values aren’t showing up, and the replacement logic goes haywire.Overly Greedy & Unescaped Regex
The^my \@old_array.*regex uses a greedy.*that can match beyond the end of the array line. Worse, the@symbol is a special character in shells—if your escaping isn’t perfect, it might get interpreted as a shell variable, turning your regex into something that matches almost any line starting withmy.Trailing Comma Syntax Error
Your loop to build$listadds an extra trailing comma (e.g.,value1, value2,), which will break Perl syntax in Script B once replaced.
Solution 1: Fix the Shell Command (Quick Fix)
Adjust the quoting and regex to properly expand $list and target only the exact array line:
# Script A code my @new_values = ('new_val1', 'new_val2', 'new_val3'); # Use join to avoid trailing commas (cleaner than looping) my $list = join(', ', @new_values); # Use double-quoted qq{} to expand $list, with proper escaping for Perl/shell my $replace_cmd = qq{perl -pi -e 's/^my \\@old_array\\s*=\\s*\\(.*?\\);/my \\@new_array = ( $list );/' script_B.pl}; system($replace_cmd);
Key Fixes:
join(', ', @new_values)builds a valid list without extra trailing commas.qq{}lets$listexpand while keeping Perl regex characters (like@and()) properly escaped.- The regex uses
\s*to allow whitespace around=and.*?(non-greedy match) to only capture content inside the array parentheses, preventing over-matching.
Solution 2: Modify Script B Directly (More Reliable)
Calling an external Perl process can be fragile due to shell escaping. A better approach is to have Script A directly edit Script B:
# Script A code my @new_values = ('new_val1', 'new_val2', 'new_val3'); my $new_array_line = 'my @new_array = (' . join(', ', @new_values) . ');'; # Open Script B for reading and a temp file for writing open my $in_fh, '<', 'script_B.pl' or die "Can't open script_B.pl: $!"; open my $out_fh, '>', 'script_B.pl.tmp' or die "Can't create temp file: $!"; while (my $line = <$in_fh>) { # Replace only the exact old array line $line =~ s/^my \@old_array\s*=\s*\(.*?\);/$new_array_line/; print $out_fh $line; } # Swap the temp file with the original close $in_fh; close $out_fh; rename 'script_B.pl.tmp', 'script_B.pl' or die "Can't update script_B.pl: $!";
Why This Is Better:
- No shell escaping headaches—everything stays within Perl.
- Total control over which lines get replaced (no accidental matches).
- Easier to debug: you can check the temp file before overwriting the original.
内容的提问来源于stack exchange,提问作者Zero

