Если я вас понимаю, цель состоит в том, чтобы извлечь содержимое input.file в различные файлы, избегая блоков потери с одинаковыми именами.
Если это так, и если целевой каталог всегда пуст перед извлечением, тогда есть лучшее (и более быстрое) решение:
awk '
/DATA/{
block=$2;
n = blocks[block]++;
file=block (n? "_" n: "");
}
/DATA/,/END/{
print > file
}' input.file
Таким образом, awk не нужно выполнять новую оболочку N раз просто чтобы проверить, существует ли файл.
Примечания:
'\'
в конце строк,
, потому что одинарная кавычка уже является многострочной. Сначала я расскажу о том, что Debian, а в большинстве случаев и Ubuntu устанавливает для bash. И последние касаются других систем.
В настройке стартовых файлов оболочки много мнений.
У меня тоже есть свое мнение, но я постараюсь показать существующие примеры правильных настроек.
Я буду использовать debuan, так как очень легко найти примеры его файлов.
И Debian активно используется, поэтому настройки были хорошо протестированы,
Только для того, чтобы узнать, интерактивна ли оболочка.
значение по умолчанию /etc/profile
в Debian и Ubuntu (из /usr/share/base -files/profile):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
Если читается :, если интерактивный (PS1 установлен по умолчанию )и это оболочка bash (, но не действует по умолчанию sh
), затем измените PS1 на конкретный новый (не по умолчанию ).
по умолчанию /etc/bash.bashrc
в debian также содержит:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Что довольно ясно в том, что он делает :Если интерактивный, не используйте источник (остальное ).
Однако,в /etc/skel/.bashrc
— это пример правильного способа тестирования интерактивной оболочки (с использованием$-
):
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Это должно ясно показать, почему PS1 и одна альтернатива.
Следует избегать настройки, о которой вы сообщаете.
Порядок (от системных настроек к более конкретным пользовательским настройкам (для bash ))следующий: /etc/profile
, /etc/bash.bashrc
, ~/.profile
и, наконец, ~/.bashrc
. Это помещает самые широкие эффекты (и больше оболочек )в /etc/profile
(, которым владеет root ), за которым следует /etc/bash.bashrc
(, который также принадлежит root ), но влияет только на bash. Затем идут личные настройки в $HOME
, первая — ~/.profile
для большинства оболочек и~/.bashrc
(почти эквивалентна ~/.bash_profile
), характерна только для bash.
Таким образом, неправильно исходить ~/.bashrc
из ~/.profile
, так как это преобразует конкретную пользовательскую настройку для bash в более общую, влияющую на большее количество оболочек . За исключением случаев, когда делается таким образом:
# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include.bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Он проверяет, запущен ли bash, и загружает только .bashrc
, если это так.
Это вышестоящее решение исходит от Debian. Обоснование объяснено здесь .
На самом деле, обратное, поиск ~/.profile
в~/.bash_profile
(или~/.bashrc
)— это только повторное -применение общих правил, которые уже должны были быть загружены к конкретному варианту использования, и, следовательно, «не так уж плохо» (Я не говорю "хорошо" ). И я не говорю хорошо, потому что это может привести к зацикливанию поиска файлов. Например, когда подкаталог -загружает родительский каталог, это цикл каталога.
И именно в этом кросс-сорсинге имеет смысл проверка интерактивной оболочки. Только когда интерактивная оболочка загружается ~/.bashrc
, но она, в свою очередь, может загружаться~/.profile
(или наоборот ), и в этом случае можно использовать проверку интерактивной оболочки.
Это проверка того, является ли оболочка интерактивной или нет. В этом случае поиск файла ~/.bash_profile
возможен только в том случае, если интерактивная оболочка.
См. «Интерактивна ли эта оболочка?» в руководстве bash, в котором цитируется эта конкретная идиома. (Также рекомендуется проверять интерактивную оболочку, проверяя, содержит ли специальная переменная $-
символ i
, что является лучшим подходом к этой проблеме.)
Это широко распространенный способ проверки интерактивности оболочки. Помните, что он работает только в bash, он не работает с другими оболочками. Так что ладно (если глупо )для .bashrc
, но это не сработает в.profile
(который читает sh, а bash это только одна из возможных реализаций sh, и не самая распространенная ).
Интерактивная оболочка устанавливает переменную оболочкиPS1
в строку приглашения по умолчанию. Таким образом, если интерактивная оболочка, PS1
устанавливается (, если пользователь .bashrc
не удалил ее, чего еще не могло произойти в верхней части .bashrc
, и вы могли бы подумать, что это глупо все равно делать ).
Обратное верно для bash :не -интерактивных экземпляров bash unset PS1
при их запуске. Обратите внимание, что такое поведение характерно для bash и, возможно, является ошибкой (. Почему bash -c '… do stuff with $var…'
не работает, если var
равно PS1
? ). Но все версии bash до 4.4 (включительно, последняя версия, которую я пишу ), делают это.
Многие системы экспортируют PS1
в среду. Это плохая идея, потому что многие разные оболочки используют PS1
, но с другим синтаксисом (, например. экранирование приглашения bash полностью отличается от экранирования приглашения zsh). Но это настолько широко распространено, что на практике установка PS1
не является надежным показателем того, что оболочка интерактивна. Оболочка могла унаследовать PS1
от среды.
.bashrc
— это файл, который bash читает при запуске, когда он интерактивен.Менее известный -факт заключается в том, что bash также читает .bashrc
как оболочку входа в систему, и эвристика bash заключает, что это удаленный сеанс (bash проверяет, является ли его родителем rshd
илиsshd
). Во втором случае маловероятно, что PS1
будет установлен в среде, потому что еще не запущен ни один точечный файл.
Однако то, как код использует эту информацию, приводит к обратным результатам.
.bash_profile
выполняется в этой оболочке. Но .bash_profile
— это сценарий времени входа -. Он может запускать некоторые программы, предназначенные для запуска только один раз за сеанс. Это может переопределить некоторые переменные среды, для которых пользователь преднамеренно установил другое значение перед запуском этой оболочки. Запуск .bash_profile
в оболочке входа без -нарушает работу. .bash_profile
. Но это тот случай, когда загрузка .bash_profile
может быть полезной, потому что интерактивная оболочка входа без -не загружает автоматически /etc/profile
и ~/.profile
. Я думаю, люди делают это по той причине, что пользователи, которые входят в систему через графический интерфейс (, что является очень распространенным случаем )и которые устанавливают свои настройки переменных среды в .bash_profile
, а не .profile
. Большинство механизмов входа в систему с графическим интерфейсом вызывают .profile
, но не .bash_profile
(, чтение .bash_profile
потребует запуска bash как части запуска сеанса вместо sh ). В этой конфигурации, когда пользователь открывает терминал, он получает свои переменные среды. Однако пользователь не получит свои переменные среды в приложениях с графическим интерфейсом, что является очень распространенным источником путаницы. Решение здесь состоит в том, чтобы использовать .profile
вместо .bash_profile
для установки переменных среды. Добавление моста между .bashrc
и .bash_profile
создает больше проблем, чем решает.
Есть прямой,портативный способ проверить, является ли текущая оболочка интерактивной :проверить, включена ли опция -i
.
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
Это полезно в .bashrc
для чтения .profile
только в том случае, если оболочка не -интерактивная — т. е. противоположное тому, что делает код! Прочтите .profile
, если bash является (не -интерактивной )оболочкой входа в систему, и не читайте ее, если это интерактивная оболочка.
if [[ $- != *i* && -r ~/.profile ]]; then. ~/.profile; fi
Похоже, что эта странная концепция является результатом того факта, что bash
запускался не как клон оболочки POSIX, а как клон Bourne Shell
.
В результате интерактивное поведение POSIX ($ENV
, которое вызывается для интерактивных оболочек ), было добавлено позже к bash
и не получило широкой известности.
Существует одна оболочка, обеспечивающая аналогичное поведение. Это csh
, и csh предоставляет, что $prompt
имеет определенные значения :
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
Но это не относится ни к Bourne Shell, ни к оболочкам POSIX.
Для оболочки POSIX:единственный разрешенный метод - поместить код для интерактивных оболочек в файл:
$ENV
с именем, характерным для оболочки. Это, например,.
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
Другие люди упомянули флаг оболочки -i
, но его нельзя использовать для надежного программирования. POSIX не требует, чтобы set -i
работал, и чтобы $-
содержал i
для интерактивных оболочек. POSIX просто требует, чтобы sh -i
переводил оболочку в интерактивный режим.
Поскольку переменная $PS1
может быть импортирована из среды, она может иметь значение даже в не-интерактивном режиме. Тот факт, чтоbash
unset
s PS1
в любой не -интерактивной оболочке, не предусмотрен стандартом и не выполняется никакой другой оболочкой.
Таким образом, чистое программирование (даже сbash
)заключается в том, чтобы помещать команды для интерактивных оболочек в $HOME/.bashrc
.