У меня есть следующий простой сценарий, в котором я запускаю цикл и хочу сохранить файл COUNTER
. Я не могу понять, почему счетчик не обновляется. Это связано с созданием подоболочки? Как я могу это исправить?
#!/bin/bash
WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' |
(
while read WFY_URL
do
echo $WFY_URL #Some more action
COUNTER=$((COUNTER+1))
done
)
echo $COUNTER # output = 0
Ответы:
Во-первых, вы не увеличиваете счетчик. Переход
COUNTER=$((COUNTER))
наCOUNTER=$((COUNTER + 1))
илиCOUNTER=$[COUNTER + 1]
увеличит его.Во-вторых, как вы предполагаете, сложнее передать переменные подоболочки вызываемому объекту. Переменные в подоболочке недоступны вне подоболочки. Это переменные, локальные для дочернего процесса.
Один из способов решить эту проблему - использовать временный файл для хранения промежуточного значения:
источник
$[...]
она устарела? Есть ли альтернативное решение?$[...]
использовалсяbash
до того, как$((...))
был принят в оболочку POSIX. Я не уверен, что он когда-либо был официально объявлен устаревшим, но я не могу найти упоминания о нем наbash
странице руководства , и, похоже, он поддерживается только для обратной совместимости....
ПРОВЕРЕННАЯ BASH: Centos, SuSE, RH
источник
$[ ]
синтаксис устарел. stackoverflow.com/questions/10515964/…- довольно неуклюжая конструкция в современном программировании.
выглядит более «современно». Вы также можете использовать
если вы думаете, что это улучшает читаемость. Иногда Bash предоставляет слишком много способов делать что-то - я полагаю, философия Perl - когда, возможно, Python «есть только один правильный способ сделать это» может быть более подходящим. Это спорное утверждение, если когда-либо был один! В любом случае, я бы предложил цель (в данном случае) не просто увеличить переменную, но (общее правило) также написать код, который кто-то может понять и поддержать. Соответствие имеет большое значение для достижения этого.
НТН
источник
Попробуй использовать
вместо того
источник
let "COUNTER++"
(( COUNTER++ ))
(без знака доллара)(( COUNTER++ ))
но когда я переключился наCOUNTER=$((COUNTER + 1))
него, он работал.GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Я думаю, что этот единственный вызов awk эквивалентен вашему
grep|grep|awk|awk
конвейеру: пожалуйста, проверьте его. Ваша последняя команда awk, похоже, ничего не меняет.Проблема с COUNTER заключается в том, что цикл while выполняется в подоболочке, поэтому любые изменения в переменной исчезают при выходе из подоболочки. Вам необходимо получить доступ к значению COUNTER в той же подоболочке. Или воспользуйтесь советом @DennisWilliamson, используйте подстановку процесса и вообще избегайте подоболочки.
источник
источник
Вместо использования временного файла вы можете избежать создания подоболочки вокруг
while
цикла, используя подстановку процесса.Кстати, у вас должно получиться все это
grep, grep, awk, awk, awk
превратить в одинawk
.Начиная с Bash 4.2, есть
lastpipe
возможностьисточник
lastpipe
. Кстати, вам, вероятно, следует использовать"${PIPESTATUS[@]}"
(вместо звездочки).минималист
источник
Это все, что вам нужно сделать:
Вот отрывок из книги Learning the bash Shell , 3rd Edition, pp. 147, 148:
..........................
См. Http://www.safaribooksonline.com/a/learning-the-bash/7572399/
источник
if
утверждения:if [[ $((needsComma++)) -gt 0 ]]; then printf ',\n'; fi
правильно или неправильно, это единственная версия, которая работала надежно.i=1; while true; do echo $((i++)); sleep .1; done
if (( needsComma++ > 0 )); then
илиif (( needsComma++ )); then
Это простой пример
источник
Похоже, вы не обновляли
counter
скрипт, используйтеcounter++
источник
У
((var++))
меня было два условия, из-за которых выражение не удалось:Если я установлю bash в строгий режим (
set -euo pipefail
) и начну приращение с нуля (0).Начать с единицы (1) нормально, но ноль приводит к тому, что приращение возвращает «1» при оценке «++», что является ошибкой ненулевого кода возврата в строгом режиме.
Я могу использовать
((var+=1))
илиvar=$((var+1))
избежать этого поведенияисточник
В исходном скрипте есть проблема с подоболочкой. Первый пример, вам, вероятно, не нужна подоболочка. Но мы не знаем, что скрыто под «Еще несколько действий». Самый популярный ответ содержит скрытую ошибку, которая увеличит количество операций ввода-вывода и не будет работать с подоболочкой, поскольку восстанавливает внутренний цикл.
Не добавляйте знак '\', он проинформирует интерпретатор bash о продолжении строки. Я надеюсь, что это поможет вам или кому-то еще. Но, на мой взгляд, этот сценарий должен быть полностью преобразован в сценарий AWK или переписан на python с использованием regexp или perl, но популярность Perl с годами падает. Лучше сделать это на питоне.
Исправленная версия без подоболочки:
Версия с подоболочкой, если она действительно нужна
источник