Как экранировать как одинарные кавычки, так и восклицательные знаки в bash

Вопрос или проблема

У меня есть длинная команда, и я просто хочу использовать alias, чтобы сократить её. Но команда содержит одинарные кавычки и восклицательные знаки.

Исходная команда: ldapsearch -x -H ... -w 'abc!123'.

Я пробовал alias search="ldapsearch -x -H ... -w \"abc!123\'' или alias search="ldapsearch -x -H ... -w 'abc!123'" и так далее. Но ни один из них не работает для меня.

! является проблемой только для расширения истории. Расширение истории происходит только в интерактивных оболочках (если не отключено пользователем, как я это делаю) и в bash (как в zsh, но в отличие от csh, где обе функции – расширение истории и алиасы – происходят) выполняется до расширения алиасов и не выполняется снова после их расширения, так что нормально оставлять ! без кавычек в значении алиаса:

alias search="ldapsearch -x -H ... -w abc!123"

Такая команда alias будет нормально работать даже в интерактивной оболочке, потому что в bash (как и в zsh, но в отличие от csh) одинарные кавычки предотвращают срабатывание !, ^… в расширении истории.

Чтобы заключить ! в одинарные кавычки в значении алиаса, вам придется делать такие вещи:

alias search="ldapsearch -x -H ... -w "\'abc\!123\'
alias search=$'ldapsearch -x -H ... -w \'abc!123\''
alias search="ldapsearch -x -H ... -w "\''abc!123'\'
alias search="ldapsearch -x -H ... -w 'abc"\!"123'"
alias search=ldapsearch\ -x\ -H\ ...\ -w\ \'abc\!123\'

То есть убедитесь, что ! заключен либо в '...', $'...', либо \ (вне любых других форм кавычек), а не в двойные кавычки.

Использование "abc!123" работает в неинтерактивных оболочках, но не в интерактивных. "abc\!123" работает в интерактивных, но не в неинтерактивных.

Вместо алиаса вы можете использовать функцию (alias стали популярными, потому что они появились в csh (примерно в 1979 году) до того, как Bourne shell добавил функции (примерно в 1983), но они на самом деле являются изъяном в оболочках в наши дни).

search() { ldapsearch -x -H ... -w 'abc!123' "$@"; }

Или даже возможно лучше, сделайте это:

#! /bin/sh -
exec ldapsearch -x -H ... -w 'abc!123' "$@"

Тогда вы сможете вызывать её откуда угодно, а не только из ваших интерактивных оболочек.

Теперь передача пароля в командной строке является очень плохой практикой, так как аргументы командной строки являются публичной информацией на большинстве систем. Они появляются в выводе ps -f, они сохраняются в историях оболочки или в журналах аудита.

Вместо этого вы должны использовать что-то такое:

search() {
  ldapsearch -x -H ... -y ~/.config/secrets/ldap/host.password "$@"
}

С ~/.config/secrets/ldap/host.password, доступным только для вас и содержащим пароль, или:

search() {
  ldapsearch -x -H ... -y <(
    command-that-retrieves-the-password from your password manager
  )  "$@"
}

Хранение пароля в вашем алиасе может иметь последствия для безопасности. Я бы посоветовал использовать функцию и параметризовать пароль следующим образом. Например

ldap_search() {
    локальный password="$1"
    ldapsearch -x -H ... -w "$password"
} 

Затем вы должны будете загрузить свой файл bashrc

source ~/.bashrc

Затем используйте функцию следующим образом:

ldap_search "<Вставьте здесь ваш пароль>"

Подсказка: Вы также можете использовать read -s -p 'Введите пароль: ' password, чтобы пароль не отображался в вашем файле истории.

Расширение истории актуально только при использовании bash интерактивно.

Переход на одинарные кавычки не всегда целесообразен. Экранирование восклицательных знаков без использования одинарных кавычек является странным и добавляет отлично к цитированию в цитировании в bash:
Вы можете использовать !”” вместо !, потому что “” внутри двойных кавычек является пустым, а !” не является расширением истории с версии bash 4.3.

$>A=”git commit -m “Разочаровывающее !”” Снаружи темно в $(date +%B)”; make” ; echo $A;

git commit -m “Разочаровывающее ! Снаружи темно в Ноябре”; make

bash -c $A

или char, не следуемый за динамической строкой b:

$>b=’b’ ; echo “abac” | grep -P “.(?!””$b)”

abac (#отрицательный просмотр вперед)

Интерактивная настройка алиаса:

$> alias ldapsearch=”ldapsearch -x -H … -w ‘abc!””123′”

.. с дополнительным пробелом в начале, чтобы по крайней мере предотвратить запись пароля в историю bash. Пожалуйста, смотрите другие ответы относительно паролей.

Ответ или решение

Для сокрытия как одинарных кавычек, так и восклицательных знаков в bash существует несколько подходов, каждый из которых зависит от контекста использования (интерактивные или неинтерактивные оболочки) и ваших конкретных требований. В данном ответе мы рассмотрим несколько методов, включая использование alias, функции, а также внимание к безопасности при хранении паролей.

Эскейпинг одинарных кавычек и восклицательных знаков в alias

Вы дадите команду ldapsearch, содержащую восклицательный знак в пароле в одинарных кавычках:

ldapsearch -x -H ... -w 'abc!123'

Для создания alias вы можете использовать несколько подходов, учитывая, что восклицательные знаки в интерактивной оболочке выполняют расширение истории. Ниже приведены различные варианты, как это сделать:

  1. Прямой способ:

    Важно помнить, что восклицательный знак не будет вызывать расширение истории, если он находится в одинарных кавычках. Таким образом, следующий вариант будет работать в интерактивных сеансах:

    alias search="ldapsearch -x -H ... -w 'abc!123'"
  2. Экранирование:

    Если вы хотите использовать восклицательный знак с точной экранировкой, вы можете использовать следующее:

    alias search="ldapsearch -x -H ... -w 'abc\!123'"

    В этом случае восклицательный знак будет интерпретироваться как обычный символ.

  3. Использование $'':

    Вы также можете воспользоваться синтаксисом ANSI-C, который позволяет вам использовать специальные символы:

    alias search=$'ldapsearch -x -H ... -w \'abc!123\''
  4. Совмещение кавычек:

    Можно комбинировать кавычки разного типа:

    alias search="ldapsearch -x -H ... -w 'abc!123'"

Функции вместо alias

Использование функций вместо alias более гибкое и безопасное решение. Например, вы можете определить функцию, которая позволяет задавать пароль в качестве параметра:

search() {
    ldapsearch -x -H ... -w "$1"
}

При этом вы можете вызвать функцию следующим образом:

search 'abc!123'

Это также поможет избежать проблем с безопасностью, связанных с тем, что пароль может отображаться в истории команд.

Безопасное управление паролями

Передача паролей в командной строке может привести к утечке данных, так как они могут быть видны в истории команд или в выводе процесса ps. Вместо этого рассмотрите возможность хранения пароля в файле и его чтения в процессе выполнения команды. Например:

search() {
    ldapsearch -x -H ... -y ~/.config/secrets/ldap/host.password "$@"
}

Вы можете создать файл ~/.config/secrets/ldap/host.password, который будет доступен только вам, и хранить в нем пароль.

Заключение

Экранирование одинарных кавычек и восклицательных знаков в bash требует аккуратного подхода, особенно если вам нужно взаимодействовать с инструментами, которые используют эти символы. Сложные комбинации кавычек и функции предлагают более безопасные и управляемые решения. Обязательно учитывайте безопасность ваших данных, избегая передачи паролей в явном виде в командной строке.

Оцените материал
Добавить комментарий

Капча загружается...