фрагменты многострочных команд в истории bash на несколько строк

В Bash (а также в Bash в WSL) многострочные записанные команды могут правильно выполнять обратный вызов с помощью стрелок вверх / вниз, а также встроенная команда history сообщает о них правильно (пока я не m все еще авторизован в bash).

Но после выхода из bash и нажатия стрелок вверх / вниз каждая многострочная команда отображается как отдельные записи, и это потому, что cat ~ / .bash_history забросил команду на несколько отдельных записей. и проблема записи здесь; результат команды history тоже был неверным.

Я установил эти параметры в ~ / .bashrc

shopt -s cmdhist lithist
HISTTIMEFORMAT='%F %T '

, и теперь исправлена ​​проблема записи , но команда history по-прежнему выводит отчеты в несколько строк и отдельные записи ( проблема чтения сейчас).

Версия Bash - 4.3, такая же проблема на v4.4

есть этот отчет об ошибке уже много лет, но решения пока нет.

Обновление:

также следует упомянуть, что приведенная ниже многострочная команда в качестве примера правильно отображается даже после выхода из Bash:

for i in {1..10}
do
echo $i
done

, но это дает сбой:

awk '
{ print $1}' <<<'first last'

Обновление 2:

проблема, упомянутая выше, исправлена в Bash v5.0.0 + это изменено для распознавания записей между «отметкой времени в качестве разделителя» как отдельной записи команды (необходимо установить HISTTIMEFORMAT , cmdhist и lithist )) .

0
задан 11 April 2019 в 22:24

1 ответ

Я использую GNU bash, версия 5.0.3 (1) -release на Ubuntu 19.10 . Я проверил и подтвердил, что проблема, описанная в вашем вопросе, существует.

Затем я решил это, выполнив следующие действия. После этого я несколько раз выходил из bash и подтверждал, что проблема в моей системе решена. Многострочные команды сохраняются в файле ~ / .bash_history , извлекаются и выполняются правильно.


Решение:

Измените файл ~ / .bashrc или создайте его, если он не существует.

Скопируйте и вставьте в него следующие три строки и сохраните:

shopt -s cmdhist
shopt -s lithist
HISTTIMEFORMAT='%F %T '

Из справочных страниц bash:

cmdhist :

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

lithist :

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

Однако cmdhist и lithist полезны, пока оболочка все еще открыта и работает из памяти. Когда вы выходите из оболочки, команды сохраняются в файле ~ / .bash_history в виде отдельных строк без каких-либо указаний относительно того, где начинается или заканчивается многострочная команда, а затем рабочая память очищается.Когда вы снова запустите оболочку, эти строки в файле истории bash (включая многострочные команды) будут считываться по одной строке за раз, и каждая строка будет обрабатываться и загружаться в рабочую память как одна команда, даже если это может быть часть многострочной команды, потому что файл ~ / .bash_history будет выглядеть так:

nano .bashrc 
exit
history 
for i in {1..10}
do
echo $i
done
cat .bash_history 
exit
history 
awk '
{ print $1}' <<<'first last'
history
exit

Следовательно, необходим HISTTIMEFORMAT , который будет действовать как разделитель для отделения каждой команды от другой - на основе его отметки времени, будь то однострочная или многострочная команда. Таким образом, файл ~ / .bash_history будет выглядеть так:

nano .bashrc 
#1581635697
exit
#1581635709
history 
#1581635729
for i in {1..10}
do
echo $i
done
#1581635743
cat .bash_history 
#1581635757
exit
#1581635773
history 
#1581635794
awk '
{ print $1}' <<<'first last'
#1581635801
history
#1581635808
exit

Из справочных страниц bash:

HISTTIMEFORMAT :

Если эта переменная установлена, а не null, ее значение будет используется как строка формата для strftime (3) для печати связанной отметки времени с каждой записью истории, отображаемой встроенной историей. Если это установлена ​​переменная, отметки времени записываются в файл истории, поэтому они может сохраняться в сеансах оболочки. Это использует комментарий истории символ, чтобы отличать отметки времени от других строк истории.

Отныне многострочные команды будут извлекаться, обрабатываться и загружаться в рабочую память как единое целое (без разделения их на отдельные строки и обработки каждой строки как отдельной команды) и вывод команды history будет выглядеть так ( даже после перезапуска bash ):

raffa@Laptop:~$ history
   1  2020-02-14 05:25:19 nano .bashrc 
   2  2020-02-14 05:25:38 exit
   3  2020-02-14 05:25:50 history
   4  2020-02-14 05:27:50 for i in {1..10}
do
echo $i
done
   5  2020-02-14 05:28:05 cat .bash_history
   6  2020-02-14 05:28:14 exit
   7  2020-02-14 05:28:27 history
   8  2020-02-14 05:28:55 awk '
{ print $1}' <<<'first last'
   9  2020-02-14 05:29:06 history
  10  2020-02-14 05:29:16 exit
  11  2020-02-14 05:29:27 history

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


Примечание:

  • Вам нужно будет перезапустить текущий сеанс bash после редактирования и сохранения файла ~ /.bashrc , чтобы активировать изменения.
  • Если ваш текущий файл ~ / .bash_history или рабочая память bash уже содержат строки истории с ошибками форматирования, вам может потребоваться удалить ( Сначала сделайте резервную копию ) текущую историю bash. запустив history -w; history -c в терминале, что навсегда удалит всю вашу текущую историю bash.

Удачи

10
ответ дан 13 February 2020 в 23:59

Другие вопросы по тегам:

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