Увеличение переменной внутри цикла Bash
Я пытаюсь написать небольшой script, который будет считать записи в файле журнала, и я увеличиваю переменную (USCOUNTER
), которую я пытаюсь использовать после завершения цикла.
Но в этот момент USCOUNTER
выглядит как 0 вместо фактического значения. Любая идея, что я делаю неправильно? Спасибо!
FILE=$1
tail -n10 mylog > $FILE
USCOUNTER=0
cat $FILE | while read line; do
country=$(echo "$line" | cut -d' ' -f1)
if [ "US" = "$country" ]; then
USCOUNTER=`expr $USCOUNTER + 1`
echo "US counter $USCOUNTER"
fi
done
echo "final $USCOUNTER"
Он выводит:
US counter 1
US counter 2
US counter 3
..
final 0
Ответы
Ответ 1
Вы используете USCOUNTER
в подоболочке, поэтому переменная не отображается в основной оболочке.
Вместо cat FILE | while ...
сделайте только a while ... done < $FILE
. Таким образом, вы избегаете общей проблемы Я устанавливаю переменные в цикле, которые в конвейере. Почему они исчезают после завершения цикла? Или, почему я не могу передать данные для чтения?:
while read country _; do
if [ "US" = "$country" ]; then
USCOUNTER=$(expr $USCOUNTER + 1)
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Примечание. Я также заменил выражение `` на $().
Я также заменил while read line; do country=$(echo "$line" | cut -d' ' -f1)
на while read country _
. Это позволяет вам сказать while read var1 var2 ... varN
, где var1
содержит первое слово в строке, $var2
и т.д., Пока $varN
не содержит оставшегося содержимого.
Ответ 2
while read -r country _; do
if [[ $country = 'US' ]]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Ответ 3
Вы получаете final 0
, потому что ваш while loop
выполняется в процессе sub (shell), и любые сделанные там изменения не отражаются в текущей (родительской) оболочке.
Исправить script:
while read -r country _; do
if [ "US" = "$country" ]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Ответ 4
минималистский
counter=0
((counter++))
echo $counter
Ответ 5
У меня была та же самая переменная $ count в цикле while, которая была потеряна.
Ответ @fedorqui (и несколько других) - это точные ответы на актуальный вопрос: проблема заключается в дополнительной оболочке.
Но это привело меня к другой проблеме: я не передавал содержимое файла... но выводил серию каналов и greps...
мой ошибочный пример кода:
count=0
cat /etc/hosts | head | while read line; do
((count++))
echo $count $line
done
echo $count
и мое исправление благодаря помощи этой темы и процесса подстановки:
count=0
while IFS= read -r line; do
((count++))
echo "$count $line"
done < <(cat /etc/hosts | head)
echo "$count"
Ответ 6
USCOUNTER=$(grep -c "^US " "$FILE")
Ответ 7
Приращение переменной может быть выполнено следующим образом:
_my_counter=$[$_my_counter + 1]
Подсчет количества появления шаблона в столбце может быть выполнен с помощью grep
grep -cE "^([^ ]* ){2}US"
-c
count
([^ ]* )
Чтобы обнаружить колонию
{2}
номер столбняка
US
ваш шаблон
Ответ 8
Использование следующей команды 1 строки для изменения имени многих файлов в Linux с использованием специфики фразы:
find -type f -name '*.jpg' | rename 's/holiday/honeymoon/'
Для всех файлов с расширением ".jpg", если они содержат строку "праздник", замените ее на "медовый месяц". Например, эта команда переименует файл "ourholiday001.jpg" на "ourhoneymoon001.jpg".
В этом примере также показано, как использовать команду find для отправки списка файлов (-type f) с расширением .jpg(-name '*.jpg') для переименования через канал (|). rename затем считывает свой список файлов со стандартного ввода.