Как исправить ошибочную подстановку переменных в perl - PullRequest
0 голосов
/ 07 ноября 2019

Я создаю несколько лексиконов для программы распознавания слов, содержащей только 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

К сожалению, значение $ngram не распознается Perl, и команда не работает должным образом. Для сравнения, этот скрипт работает:

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. Однако я ищу решение, чтобы я мог просто запустить команду в терминале.

Ответы [ 2 ]

3 голосов
/ 07 ноября 2019

Perl не имеет доступа к переменным оболочки, и оболочка не может ничего менять в одинарных кавычках - здесь нет «недопустимой подстановки», потому что здесь вообще нет подстановки. Решение состоит в том, чтобы передать значение в Perl в качестве аргумента или (не в идеале) сделать так, чтобы оболочка внедрила значение в источник 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

Это также удаляет бесполезный cat и исправляет незначительную ошибку цитирования.

2 голосов
/ 07 ноября 2019

В вашем исходном коде $ngram является переменной оболочки. Но превратите его в переменную окружения, и 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
...