Почему мой счетчик Bash сбрасывается после цикла while

У меня есть сценарий Bash, в котором я хочу подсчитать, сколько всего было сделано при циклическом просмотре файла. Кажется, что счетчик работает внутри цикла, но после него переменная кажется сброшенной.

nKeys=0
cat afile | while read -r line
do
  #...do stuff
  let nKeys=nKeys+1
  # this will print 1,2,..., etc as expected
  echo Done entry $nKeys
done
# PROBLEM: this always prints "... 0 keys"
echo Finished writing $destFile, $nKeys keys

Результатом вышеупомянутого является что-то одно:

Готово запись 1
Готово запись 2
Готовая запись / бла, 0 клавиш

Я хочу получить вывод:

Готово запись 1
Готово запись 2
Готовая запись / бла, 2 ключа

Я не совсем уверен, почему nKeys равен 0 после цикла:(Я предполагаю, что это что-то простое, но, черт возьми, я могу это заметить, несмотря на то, что смотрю на http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html и другие ресурсы.

Скрестив пальцы, кто-то другой может взглянуть на это и сказать: "Ну, да! Ты должен..."!

3 ответа

В только что выпущенном Bash 4.2 вы можете сделать это, чтобы предотвратить создание подоболочки:

shopt -s lastpipe

Кроме того, как вы, вероятно, увидите по предоставленной Игнасио ссылке, у вас есть Бесполезное использованиеcat,

while read -r line
do
    ...
done < afile

Как уже упоминалось в принятом ответе, это происходит потому, что каналы порождают отдельные подпроцессы. Чтобы избежать этого, command grouping был лучшим вариантом для меня. То есть делаю все после трубы в подоболочку.

nKeys=0
cat afile | 
{
  while read -r line
  do
    #...do stuff
    let nKeys=nKeys+1
    # this will print 1,2,..., etc as expected
    echo Done entry $nKeys
  done
  # PROBLEM: this always prints "... 0 keys"
  echo Finished writing $destFile, $nKeys keys
}

Теперь он сообщит значение $nKeys "правильно" (то есть то, что вы хотите).

Я достиг желаемого результата следующим образом, не используя трубы или здесь документы


#!/bin/sh
counter=0
string="apple orange mango egg indian"
str_len=${#string}
while [ $str_len -ne 0 ]
do
   c=${string:0:1}
   if  [[ "$c" = [aeiou] ]]
   then
       echo -n "vowel : "
       echo "- $c"
       counter=$(( $counter + 1 ))
   fi
   string=${string:1}
   str_len=${#string}
done
   printf "The number of vowels in the given string are : %s "$counter
   echo
Другие вопросы по тегам