В большинстве версий awk аргументы после исполняемой программы::
x=y
Поскольку ваше имя файла интерпретируется как case #2, awk все еще ждет, пока что-то будет прочитано на stdin (, так как он не воспринимает, что было передано какое-либо имя файла ).
При переносе это поведение задокументировано в POSIX :
.
Either of the following two types of argument can be intermixed:
- file: A pathname of a file that contains the input to be read, which is matched against the set of patterns in the program. If no file operands are specified, or if a file operand is '-', the standard input shall be used.
- assignment: An operand that begins with an underscore or alphabetic character from the portable character set (see the table in the Base Definitions volume of IEEE Std 1003.1-2001, Section 6.1, Portable Character Set), followed by a sequence of underscores, digits, and alphabetics from the portable character set, followed by the '=' character, shall specify a variable assignment rather than a pathname.
Таким образом, при переносе у вас есть несколько вариантов (#1, вероятно, наименее навязчивый):
awk..../my=file
, который обходит это, поскольку .
не является "символом подчеркивания или буквенным символом из переносимого набора символов". awk... < my=file
. Однако это не работает с несколькими файлами. ln my=file my_file
, а затем использовать my_file
как обычно. Копирование выполняться не будет, и оба файла будут поддерживаться одними и теми же данными и метаданными inode. После его использования можно безопасно удалить созданную ссылку, так как количество ссылок на индексный дескриптор все равно будет больше 0. Вы можете сделать что-то вроде:
false; while [[ $? -ne 0 ]]; do
command
done
Здесь false
изначально устанавливает $?
в ненулевое -значение, позволяя циклу запуститься по крайней мере один раз. Затем цикл выполняет данную команду до тех пор, пока не завершится с нулевым статусом выхода -.
Ключевые слова while
и until
принимают в качестве аргумента команду . Если команда возвращает нулевой статус выхода -, сигнализирующий «успех», while
будет запускать команды в теле цикла, а until
будет , а не запускать команды в теле цикла. петля.
Похоже, что ваш код использует while
и until
с $?
, статусом выхода -самой последней команды в качестве команды. Это не сработает, если в системе нет команд с целыми числами в качестве имен. Что будет работать с , так это использовать команду test
для сравнения с 0
, например, с
until test "$?" -eq 0; do some-command; done
или, используя краткую форму test
,
until [ "$?" -eq 0 ]; do some-command; done
Теперь очевидно, что проблема заключается в том, что $?
вполне может быть нулевым при входе в цикл, предотвращая выполнение цикла даже один раз. Было бы более разумно позволить самой команде передать статус выхода -непосредственно либо while
, либо until
(, если только вы не хотите инициализировать $?
ненулевым значением -, вызвав, например,. false
непосредственно перед циклом, что выглядело бы странно ).
Использование стандартного POSIX (, хотя и не Bourne, не то, чтобы это имело большое значение в наши дни )синтаксис оболочки:
while ! some-command; do continue; done
или (как Bourne, так и POSIX ),
until some-command; do continue; done
Оба этих запуска выполняются some-command
до тех пор, пока не вернут нулевой выход -статус ("успех" ). На каждой итерации он выполняет ключевое слово continue
внутри тела цикла. Выполнение continue
немедленно переходит к следующей итерации цикла,но вы можете заменить его, например. sleep 5
, чтобы иметь небольшую задержку на каждой итерации, или с :
, который ничего не делает.
Другим вариантом может быть бесконечный цикл, из которого вы выходите при успешном выполнении вашей команды:
while true; do some-command && break; done
или, немного более подробный и с добавлением воздуха для удобства чтения,
while true; do
if some-command; then
break
fi
done
Единственный раз, когда вам действительно нужно для использования $?
, это когда вам нужно какое-то время отслеживать это значение, как в
somefunction () {
grep -q 'pattern' file
ret=$?
if [ "$ret" -ne 0 ]; then
printf 'grep failed with exit code %s\n' "$ret"
fi >&2
return "$ret"
}
В приведенном выше коде статус выхода -в $?
сбрасывается тестом [ "$ret" -ne 0 ]
, и мы не смогли бы напечатать его значение или вернуть его из функции, не сохранив его в отдельной переменной.
Еще одна вещь, на которую следует обратить внимание, это то, что вы, похоже, используете строку ,$command
(без кавычек )в качестве команды. Было бы намного лучше использовать массив, если вы хотите запустить команду, хранящуюся в переменной:
thecommand=( awk -F ',' 'BEGIN { "uptime" | getline; split($4,a,": "); if (a[2] > 5) exit 1 }' )
while ! "${thecommand[@]}"; do sleep 5; done
(Код в этом примере приостанавливается с интервалом в пять секунд до тех пор, пока средняя загрузка системы за 1 -минут не опустится ниже 5.)
Обратите внимание, как с помощью массива и цитирования расширения как "${thecommand[@]}"
я могу запустить свою команду, не беспокоясь о том, как оболочка разделит строку на слова и применит подстановку имени файла к каждому из этих слов.
См. также Как запустить команду, хранящуюся в переменной? для получения дополнительной информации по этому аспекту вашей проблемы.