В
head -n 1 file > file
file
является усеченным прежде head
запускается, но если Вы пишете это:
head -n 1 file 1<> file
это не как file
открыт в режиме чтения-записи. Однако, когда head
запись концов, это не усекает файл, таким образом, строка выше была бы не (head
просто переписал бы первую строку по себе и оставил бы другие нетронутыми).
Однако после head
возвратился и в то время как fd
все еще открыто, можно назвать другую команду, которая делает truncate
.
Например:
{ head -n 1 file; perl -e 'truncate STDOUT, tell STDOUT'; } 1<> file
Какие вопросы здесь это truncate
выше, head
просто перемещает курсор для fd 1 в файле сразу после первой строки. Это действительно переписывает первую строку, к которой мы не нуждались в нем, но это не вредно.
С головой POSIX мы могли на самом деле уйти, не переписывая ту первую строку:
{ head -n 1 > /dev/null
perl -e 'truncate STDIN, tell STDIN'
} <> file
Здесь, мы используем факт это head
перемещает позицию курсора в ее stdin. В то время как head
обычно читал бы его вход большими блоками для улучшения производительности, POSIX потребует его (где возможный) к seek
назад сразу после первой строки, если это пошло вне его. Обратите внимание однако, что не все реализации делают это.
С другой стороны, можно использовать оболочку read
управляйте вместо этого в этом случае:
{ read -r dummy; perl -e 'truncate STDIN, tell STDIN'; } <> file
getopts bash используют переменную среды OPTIND для отслеживания последнего обработанного аргумента опции. Тот факт, что OPTIND
не сбрасывался автоматически каждый раз, когда вы вызывали getopts
в том же сеансе оболочки, а только при вызове оболочки. Итак, когда вы второй раз вызвали getopts
с теми же аргументами в том же сеансе, OPTIND
не был изменен, getopts
думали, что они выполнили свою работу и ничего не сделали .
Вы можете сбросить OPTIND
вручную, чтобы заставить его работать:
$ OPTIND=1
$ f -a 123
-a was triggered, Parameter: 123
или просто поместите функцию в скрипт и вызовите скрипт несколько раз.
zsh getopts немного отличается. OPTIND
обычно сбрасывался в 1 каждый раз при выходе из функции оболочки.
Необходимо установить OPTIND = 1
в начале функции f
. По умолчанию оно равно 1, но затем увеличивается по мере разбора аргументов. Когда вы вызываете getopts
снова он несет на себе, где он ушел. Вы можете увидеть это, если ваш второй вызов:
f -a 123 -a 999
, когда он напечатает 999.
Когда вызывается getopt
, он отслеживает обработанные параметры с помощью переменной OPTIND
.
Попробуйте следующее:
#!/bin/bash
f () {
printf "Intro OPTIND: %d\n" "$OPTIND"
while getopts ":a:b:" opt; do
printf "Current OPTIND: %d\n" "$OPTIND"
case $opt in
a)
echo "-a was triggered, Parameter: $OPTARG" >&2
;;
b)
echo "-b was triggered, Parameter: $OPTARG" >&2
;;
esac
done
printf "Exit OPTIND: %d\n" "$OPTIND"
}
echo "Run #1"
f "$@"
echo "Run #2"
f "$@"
Выход:
./test -a foo -b bar
Run #1
Intro OPTIND: 1
Current OPTIND: 3
-a was triggered, Parameter: foo
Current OPTIND: 5
-b was triggered, Parameter: bar
Exit OPTIND: 5
Run #2
Intro OPTIND: 5
Exit OPTIND: 5
Таким образом, вы можете сделать что-то вроде:
OPTIND=1
в начале функции. Или, в зависимости от ситуации, что обычно лучше:
local OPTIND
Если OPTIND
не использовался, поскольку функция реализована, цикл while продолжался бы вечно. Его также можно использовать для возобновления обработки аргументов, после сбоя или чего-либо еще, вызвать другую функцию, если x или y, и она возобновит работу с того места, где было остановлено ранее и т. Д.