Назначение [-n «$ PS1»] в bashrc

Если я вас понимаю, цель состоит в том, чтобы извлечь содержимое input.file в различные файлы, избегая блоков потери с одинаковыми именами.

Если это так, и если целевой каталог всегда пуст перед извлечением, тогда есть лучшее (и более быстрое) решение:

awk '
/DATA/{
    block=$2;
    n = blocks[block]++;
    file=block (n? "_" n: "");  
}
/DATA/,/END/{
    print > file
}' input.file

Таким образом, awk не нужно выполнять новую оболочку N раз просто чтобы проверить, существует ли файл.

Примечания:

  • Нет необходимости в блоке BEGIN, потому что разделителем полей awk является уже пробелов.
  • Нет необходимости в '\' в конце строк, , потому что одинарная кавычка уже является многострочной.
10
15.08.2018, 08:05
4 ответа

Сначала я расскажу о том, что Debian, а в большинстве случаев и Ubuntu устанавливает для bash. И последние касаются других систем.

В настройке стартовых файлов оболочки много мнений.
У меня тоже есть свое мнение, но я постараюсь показать существующие примеры правильных настроек.
Я буду использовать debuan, так как очень легко найти примеры его файлов.
И Debian активно используется, поэтому настройки были хорошо протестированы,

Какова цель проверки того, что PS1 установлен?

Только для того, чтобы узнать, интерактивна ли оболочка.

значение по умолчанию /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(или наоборот ), и в этом случае можно использовать проверку интерактивной оболочки.

1
27.01.2020, 19:59

Это проверка того, является ли оболочка интерактивной или нет. В этом случае поиск файла ~/.bash_profileвозможен только в том случае, если интерактивная оболочка.

См. «Интерактивна ли эта оболочка?» в руководстве bash, в котором цитируется эта конкретная идиома. (Также рекомендуется проверять интерактивную оболочку, проверяя, содержит ли специальная переменная $-символ i, что является лучшим подходом к этой проблеме.)

22
27.01.2020, 19:59

Что это делает

Это широко распространенный способ проверки интерактивности оболочки. Помните, что он работает только в bash, он не работает с другими оболочками. Так что ладно (если глупо )для .bashrc, но это не сработает в.profile(который читает sh, а bash это только одна из возможных реализаций sh, и не самая распространенная ).

Почему это работает (только в bash!)

Интерактивная оболочка устанавливает переменную оболочки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от среды.

Почему здесь используется (mis )

.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
22
27.01.2020, 19:59

Похоже, что эта странная концепция является результатом того факта, что 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может быть импортирована из среды, она может иметь значение даже в не-интерактивном режиме. Тот факт, чтоbashunsets PS1в любой не -интерактивной оболочке, не предусмотрен стандартом и не выполняется никакой другой оболочкой.

Таким образом, чистое программирование (даже сbash)заключается в том, чтобы помещать команды для интерактивных оболочек в $HOME/.bashrc.

2
27.01.2020, 19:59

Теги

Похожие вопросы