Вероятно, не рекомендуется хранить большие данные в качестве переменных из соображений переносимости и надежности. Что касается решения, отличного от awk
, которое также является POSIX, чтобы быть более портативным, используйте sed
.
Для больших объемов данных избегайте сохранения в виде переменных. Хотя Bash сам по себе не налагает ограничений, но ОС может делать это
Предположим, вы говорите: «Это работает в моей ОС». Но,
Итак, мы сохраняем ее в файле. В частности, разбейте вашу строку на один символ (или любую наименьшую единицу, которую вы хотите), на отдельные строки.
Затем используйте sed
:
sed
определен в спецификациях POSIX , чтобы выполнить ваше не AWK
, но требование POSIX Дополнительно подумайте о преимуществах обслуживания кода при использовании файла. Обновление строк, хранящихся в файле, может быть проще, чем навигация по коду в сценарии.
Имейте данные, по одному символу (или любой другой наименьшей единице, которую вы хотите «пройти») в строке, например, в файле data.lst
:
a
b
c
d
e
Имейте свой script.sh
содержат:
#!/bin/bash
stop_number="$1"
sed -n "1,${stop_number}p" data.lst
Итак, вы протестируете это в командной строке и увидите:
$ ./script.sh 3
a
b
c
sed
для печати строки 1
до числа указывается в $ stop_number
. Мы выписали $ stop_number
вместо $ 1
напрямую, для ясности $ stop_number
, конечно, получается с помощью позиционного параметра $ 1
, который равен произвольный ввод числа, который вы хотели data.lst
, в той последовательности, в которой он появляется в data.lst
data.lst
находится в том же каталоге, что и script.sh
, но если вы этого не хотите, если он у вас действительно есть где-то еще, например ~ / some / dir / data.lst
, тогда вам просто нужно настроить его так, чтобы он говорил ~ / some / dir / data.lst
Итак, как только ваши фактические данные будут в data.lst
вы можете протестировать этот скрипт самостоятельно.
С zsh
(и только zsh
) и его функцией multios
:
your-cmd 2> stdout+stderr.log >&2 2> stderr.log
Поскольку fd 2 перенаправляется дважды, zsh
реализует внутренний тройник
для отправки в оба файла.
В bash
(или любой другой оболочке типа Bourne) вы можете выполнить тройник
вручную с помощью:
{ your-cmd 2>&1 >&3 3>&- | tee stderr.log 3>&-; } > stderr+stdout.log 3>&1
(хотя вы потеряете статус выхода your-cmd
.zsh
находится в $pipestatus[1]
, bash
в "${PIPESTATUS[0]}"
(при условии, что перенаправление на stderr+stdout.log
не завершилось ошибкой)).
Чтобы записать pid your-cmd
, вы можете сделать:
{ sh -ec 'echo "$$" > /var/run/pidfile; exec your-cmd' 2>&1 >&3 3>&- |
tee stderr.log 3>&-; } > stderr+stdout.log 3>&1
С yash
и его перенаправлением процесса:
your-cmd > stdout+stderr.log 2>(tee stderr.log)
(но обратите внимание, что yash
не будет ждать завершения этой команды tee
, поэтому файлы журнала могут быть неполными к тому времени, когда вы выполните следующую команду после этого).
Нечто подобное (и с той же оговоркой) можно сделать с помощью замены процесса в bash
, zsh
и ksh93
:
{ your-cmd 2> >(tee stderr.log); } > stderr+stdout.log
Для запуска в фоновом режиме и получения pid:
(exec your-cmd 2> >(tee stderr.log)) > stderr+stdout.log & pid=$!
С rc
:
{your-cmd |[2=0] tee stderr.log} > stdout+stderr.log
каналы rc
позволяют указать, какие файловые дескрипторы подключены к каналу. В других оболочках это всегда fd 1 для левой команды и fd 0 для правой (отсюда небольшой танец с fd 3 выше для сдвига файловых дескрипторов). rc
сообщит об ошибке, если произойдет сбой либо your-cmd
, либо tee
, хотя точное число может быть потеряно.