Вопрос или проблема
Я пытаюсь найти команду, которая вернула бы мне вычисленное значение переменной $PS1 или просто командную строку с текущим путем.
Например:
foo-user@bar-pc:~\bar
Я хотел бы избежать использования чего-то вроде, поскольку pwd не будет обрезать home_dir как ~
.
echo "`whoami`@`hostname`:`pwd`"
Это реализация предложения billc.cn:
$(export PS1; echo exit | sh -i 2>&1)
Конечно, если у вас есть !
в PS1
, он будет интерпретироваться как “1”, если только у вас нет какой-то истории сохранения. Имя пользователя, имя хоста, текущий каталог, дата и время и т. д. должны быть в порядке.
Я знаю, что этот вопрос старый, но я наткнулся на него, пока исследовал аналогичную проблему. Так что, если кто-то еще окажется в такой ситуации, вот решение, которое я нашел.
Преобразование параметров Bash
Начиная с версии 4.4, bash включает функцию, называемую преобразование параметров. Она позволяет обрабатывать ваши параметры несколькими различными способами, но здесь нас интересует преобразование строки запроса. Этот тип преобразования активируется добавлением @P
к имени переменной внутри фигурных скобок (например: ${myvar@P}
).
Используя этот тип преобразования, переменная будет обрабатываться той же логикой, что и при обработке переменной $PS1
перед отображением вашей строки запроса. Это означает, что теперь вы можете получить полностью обработанный вывод вашей строки запроса, просто вызвав переменную так: "${PS1@P}"
.
Единственная загвоздка здесь в том, что многострочные строки запроса интерпретируют \n
странно. Они, похоже, используют возвраты каретки, за которыми следуют пробелы (\x0d\x20
), когда не заключены в кавычки, и возвраты каретки, за которыми следуют переводы строки (стили MS: \x0d\x0a
), когда заключены в кавычки. Это означает, что курсор возвращается к колонке 1 с возвратом каретки, но если вы не имеете перевода строки, чтобы переместить курсор на строку вниз, то текст для следующей строки просто начинает перезаписывать первую строку.
Например:
bash> PS1='\u@\h:${SHLVL}:\w\nbash> '
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> echo ${PS1}
\u@\h:${SHLVL}:\w\nbash>
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> echo ${PS1@P}
bash> adley@ENCOM1:2:/usr/src/MCP
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> echo ${PS1@P} | xxd
00000000: 616c 616e 2e62 7261 646c 6579 4045 4e43 alan.bradley@ENC
00000010: 4f4d 313a 323a 2f75 7372 2f73 7263 2f4d OM1:2:/usr/src/M
00000020: 4350 0d20 6261 7368 3e20 0a CP. bash> .
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> echo "${PS1@P}"
alan.bradley@ENCOM1:2:/usr/src/MCP
bash>
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> echo "${PS1@P}" | xxd
00000000: 616c 616e 2e62 7261 646c 6579 4045 4e43 alan.bradley@ENC
00000010: 4f4d 313a 323a 2f75 7372 2f73 7263 2f4d OM1:2:/usr/src/M
00000020: 4350 0d0a 6261 7368 3e20 0a CP..bash> .
alan.bradley@ENCOM1:2:/usr/src/MCP
bash> |
Так что, если вы хотите отобразить вашу строку запроса, как только вы ее получите, имейте в виду, что вам нужно будет заключить переменную в кавычки, чтобы многострочные строки запроса отображались правильно.
Ответ или решение
Для получения оцененного значения переменной окружения PS1 в оболочке Bash, можно использовать несколько подходов, которые позволяют безопасно извлечь форматированный вывод переменной без необходимости ручного анализа. Одним из наиболее элегантных способов является использование функции трансформации параметров, доступной в Bash начиная с версии 4.4.
Получение оцененного значения переменной PS1
Для получения фактического значения переменной PS1, которое будет отображать текущую рабочую директорию, имя пользователя и имя хоста в формате, установленном в PS1, можно воспользоваться следующей конструкцией:
echo "${PS1@P}"
Как это работает
${PS1@P}
: Использование конструкции@P
выполняет трансформацию строки, которая позволяет Bash интерпретировать специальные символы (например,\u
,\h
,\w
) так, как это делается при выводе приглашения командной строки.- Ваша команда выведет форматированное значение, например:
foo-user@bar-pc:~
, при условии что PS1 правильно настроен.
Обработка многострочных приглашений
Однако, если ваше приглашение имеет многострочную структуру, нужно учитывать, что интерпретация может привести к неэстетичному выводу:
- Без кавычек: вы можете наблюдать проблемы с отображением, причем текст может перекрывать друг друга.
- С кавычками: при использовании двойных кавычек, вы избежите проблем с форматированием (например, ненужные символы возврата каретки).
Пример правильного использования:
# Пример с многострочным приглашением
PS1='\u@\h:\w\n$ '
echo "${PS1@P}"
Альтернативные способы
Если вы не пользуетесь Bash версии 4.4 и выше, вы можете использовать команду для старых версий:
$(export PS1; echo exit | sh -i 2>&1)
Этот метод создает интерактивную оболочку, в которой переменная PS1 будет окрашена, но стоит заметить, что такой подход может привести к неожиданным результатам из-за некоторых символов, таких как !
, которые будут интерпретироваться по-другому.
Заключение
Получение значения переменной PS1 в Bash — это полезный трюк для пользователей, желающих динамически отображать свои команды, сохраняя при этом интеграцию с текущей средой. При использовании этих методов вы сможете удобно извлекать отформатированное значение PS1, минимизируя ручные операции и ошибки.
Не забудьте проверить версию вашего Bash с помощью команды bash --version
для того, чтобы выбрать наиболее подходящий метод получения значений.