如何修复 perl 中的错误变量替换
How to fix errorenous variable substitution in perl
我正在为一个只包含一个单词的 x 个第一个发音(以下简称 ngram)的单词识别程序创建几个词典。因此,我从现有词典中提取需要的词。但是,我想自动执行此操作,即找到 ngram 的所有单词(例如 ngram = 3),保存它们,增加 ngram(= 4)并重复该过程。代码如下所示:
ngrams=$(seq 3 1 9)
for ngram in $ngrams
do
cat /Lexicon/whole_lexicon.lex | perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok; if ($ngram < $ntoprint) {$ntoprint = $ngram}; for ($i = 1; $i <= $ntoprint; $i++) {printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i])); }' > lexicons/lex$ngram.txt
done
不幸的是,perl 无法识别值 $ngram
,命令无法正常运行。作为比较,此脚本有效:
ngram=3
cat /Lexicon/whole_lexicon.lex | perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok; if (3 < $ntoprint) {$ntoprint = 3}; for ($i = 1; $i <= $ntoprint; $i++) {printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i])); }' > lexicons/lex$ngram.txt
经过一些研究,我现在知道我可以编写一个 perl 脚本并将变量值 $ngram
传递给这个脚本,我可以在其中与 @ARGV
一起使用它。但是,我正在寻找一个解决方案,这样我就可以 运行 在终端中输入一个命令。
Perl 无法访问 shell 的变量,并且 shell 无法更改单引号中的任何内容 - 这里没有 "invalid substitution" 因为这里根本没有替代品。解决方案是将值作为参数传递给 Perl,或者(不太理想)让 shell 将值注入 Perl 源代码,例如通过将 Perl 脚本的一部分从单引号切换为双引号。
for ngram in $(seq 3 1 9)
do
perl -ne 'BEGIN { $ngram = shift @ARGV; }
chomp;
@tok = split(/\s+/);
$ntoprint = $#tok;
if ($ngram < $ntoprint) {$ntoprint = $ngram};
for ($i = 1; $i <= $ntoprint; $i++) {
printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i]));
}' "$ngram" < /Lexicon/whole_lexicon.lex > lexicons/"lex$ngram.txt"
done
这也删除了 useless cat
并修复了一个小的引用错误。
在您的原始代码中,$ngram
是一个 shell 变量。但是把它变成一个环境变量,Perl 就可以通过特殊的散列 %ENV
.
来访问它
export ngram # upgrade $ngram from shell to environment variable
for ngram in $ngrams
do
perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok;
if ($ENV{ngram} < $ntoprint) {$ntoprint = $ENV{ngram}};
for ($i = 1; $i <= $ntoprint; $i++) {
printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i]));
}' < /Lexicon/whole_lexicon.lex > lexicons/lex$ngram.txt
done
我正在为一个只包含一个单词的 x 个第一个发音(以下简称 ngram)的单词识别程序创建几个词典。因此,我从现有词典中提取需要的词。但是,我想自动执行此操作,即找到 ngram 的所有单词(例如 ngram = 3),保存它们,增加 ngram(= 4)并重复该过程。代码如下所示:
ngrams=$(seq 3 1 9)
for ngram in $ngrams
do
cat /Lexicon/whole_lexicon.lex | perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok; if ($ngram < $ntoprint) {$ntoprint = $ngram}; for ($i = 1; $i <= $ntoprint; $i++) {printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i])); }' > lexicons/lex$ngram.txt
done
不幸的是,perl 无法识别值 $ngram
,命令无法正常运行。作为比较,此脚本有效:
ngram=3
cat /Lexicon/whole_lexicon.lex | perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok; if (3 < $ntoprint) {$ntoprint = 3}; for ($i = 1; $i <= $ntoprint; $i++) {printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i])); }' > lexicons/lex$ngram.txt
经过一些研究,我现在知道我可以编写一个 perl 脚本并将变量值 $ngram
传递给这个脚本,我可以在其中与 @ARGV
一起使用它。但是,我正在寻找一个解决方案,这样我就可以 运行 在终端中输入一个命令。
Perl 无法访问 shell 的变量,并且 shell 无法更改单引号中的任何内容 - 这里没有 "invalid substitution" 因为这里根本没有替代品。解决方案是将值作为参数传递给 Perl,或者(不太理想)让 shell 将值注入 Perl 源代码,例如通过将 Perl 脚本的一部分从单引号切换为双引号。
for ngram in $(seq 3 1 9)
do
perl -ne 'BEGIN { $ngram = shift @ARGV; }
chomp;
@tok = split(/\s+/);
$ntoprint = $#tok;
if ($ngram < $ntoprint) {$ntoprint = $ngram};
for ($i = 1; $i <= $ntoprint; $i++) {
printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i]));
}' "$ngram" < /Lexicon/whole_lexicon.lex > lexicons/"lex$ngram.txt"
done
这也删除了 useless cat
并修复了一个小的引用错误。
在您的原始代码中,$ngram
是一个 shell 变量。但是把它变成一个环境变量,Perl 就可以通过特殊的散列 %ENV
.
export ngram # upgrade $ngram from shell to environment variable
for ngram in $ngrams
do
perl -ne 'chomp; @tok = split(/\s+/); $ntoprint = $#tok;
if ($ENV{ngram} < $ntoprint) {$ntoprint = $ENV{ngram}};
for ($i = 1; $i <= $ntoprint; $i++) {
printf("%s\t%s\n", join("", @tok[1..$i]), join(" ", @tok[1..$i]));
}' < /Lexicon/whole_lexicon.lex > lexicons/lex$ngram.txt
done