1

Это сводило меня с ума в течение трех лет. Я не знаю, как полностью описать проблему, но думаю, что смогу наконец описать способ ее воссоздания. Ваш пробег может варьироваться. У меня есть смесь серверов Ubuntu и настольных компьютеров разных версий и нескольких машин Gentoo с различными состояниями неисправности. Кажется, что они все делают свое дело, хотя и со сходством.

Попробуйте это и дайте мне знать, если вы видите то же самое.

  1. откройте два xterms (TERM = xterm)
  2. изменить размер, чтобы они не совпадали
  3. выдать экран -R test1 в одном (TERM = экран)
  4. и экран -x test1 в другом
  5. ура, набрав в одном появляется в другом; хотя обратите внимание, что их разный размер производит артефакты и вещи
  6. выдать пару команд в вашей оболочке
  7. нажмите ^ AF на тот, который не совсем подходит, теперь он подходит !!
  8. прокрутите историю немного назад
  9. перейти к 6

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

Если вы видите то, что я вижу, то вот это:

bash$ ls -al
bash$ ps auxfw

становится так:

bash$ ls -al; ps auxfw

Это не происходит каждый раз. Я должен действительно играть с этим - если я не хочу, чтобы это произошло, то это всегда происходит. В некоторых системах (или комбинациях) я получаю разделитель строк, как в примере выше. На некоторых системах у меня нет. То, что я получаю разделитель строк в некоторых системах, мне кажется, что bash поддерживает такое поведение. Его история полностью обрабатывается libreadline, и после просмотра (то есть тщательного чтения) страниц руководства я не смог найти ни одной настройки readline для объединения двух строк истории. Также я не могу найти что-либо на странице руководства bash.

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

1 ответ1

0

Из CHANGELOG для bash-4.2-rc2:

В этом документе подробно описаны изменения между этой версией bash-4.2-alpha и предыдущей версией bash-4.1-release.

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

Тарбол кандидата на релиз доступен здесь.

Редактировать:

Вот некоторые частичные различия между Bash 3.2 и Bash 4.2 RC2:

y.tab.c:

#if defined (HISTORY)                                                                                                                   #if defined (HISTORY)
/* A list of tokens which can be followed by newlines, but not by                                                                       /* A list of tokens which can be followed by newlines, but not by
   semi-colons.  When concatenating multiple lines of history, the                                                                         semi-colons.  When concatenating multiple lines of history, the
   newline separator for such tokens is replaced with a space. */                                                                          newline separator for such tokens is replaced with a space. */
static int no_semi_successors[] = {                                                                                                  |  static const int no_semi_successors[] = {
  '\n', '{', '(', ')', ';', '&', '|',                                                                                                     '\n', '{', '(', ')', ';', '&', '|',
  CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,                                                             |    CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, THEN, UNTIL,
                                                                                                                                     >    WHILE, AND_AND, OR_OR, IN,
  0                                                                                                                                       0
};                                                                                                                                      };

/* If we are not within a delimited expression, try to be smart                                                                         /* If we are not within a delimited expression, try to be smart
   about which separators can be semi-colons and which must be                                                                             about which separators can be semi-colons and which must be
   newlines.  Returns the string that should be added into the                                                                             newlines.  Returns the string that should be added into the
   history entry. */                                                                                                                 |     history entry.  LINE is the line we're about to add; it helps
                                                                                                                                     >     make some more intelligent decisions in certain cases. */
char *                                                                                                                                  char *
history_delimiting_chars ()                                                                                                          |  history_delimiting_chars (line)
                                                                                                                                     >       const char *line;
{                                                                                                                                       {
                                                                                                                                     >    static int last_was_heredoc = 0;      /* was the last entry the start of a here document? */
  register int i;                                                                                                                         register int i;

                                                                                                                                     >    if ((parser_state & PST_HEREDOC) == 0)
                                                                                                                                     >      last_was_heredoc = 0;
                                                                                                                                     >
  if (dstack.delimiter_depth != 0)                                                                                                        if (dstack.delimiter_depth != 0)
    return ("\n");                                                                                                                          return ("\n");
                                                                                                                                     |
                                                                                                                                     >    /* We look for current_command_line_count == 2 because we are looking to
                                                                                                                                     >       add the first line of the body of the here document (the second line
                                                                                                                                     >       of the command).  We also keep LAST_WAS_HEREDOC as a private sentinel
                                                                                                                                     >       variable to note when we think we added the first line of a here doc
                                                                                                                                     >       (the one with a "<<" somewhere in it) */
                                                                                                                                     >    if (parser_state & PST_HEREDOC)
                                                                                                                                     >      {
                                                                                                                                     >        if (last_was_heredoc)
                                                                                                                                     >          {
                                                                                                                                     >            last_was_heredoc = 0;
                                                                                                                                     >            return "\n";
                                                                                                                                     >          }
                                                                                                                                     >        return (current_command_line_count == 2 ? "\n" : "");
                                                                                                                                     >      }
                                                                                                                                     >
  /* First, handle some special cases. */                                                                                                 /* First, handle some special cases. */
  /*(*/                                                                                                                                   /*(*/
  /* If we just read `()', assume it's a function definition, and don't                                                                   /* If we just read `()', assume it's a function definition, and don't
     add a semicolon.  If the token before the `)' was not `(', and we're                                                                    add a semicolon.  If the token before the `)' was not `(', and we're
     not in the midst of parsing a case statement, assume it's a                                                                             not in the midst of parsing a case statement, assume it's a
     parenthesized command and add the semicolon. */                                                                                         parenthesized command and add the semicolon. */
  /*)(*/                                                                                                                                  /*)(*/
  if (token_before_that == ')')                                                                                                           if (token_before_that == ')')
    {                                                                                                                                       {
      if (two_tokens_ago == '(')        /*)*/   /* function def */                                                                            if (two_tokens_ago == '(')        /*)*/   /* function def */
        return " ";                                                                                                                             return " ";
      /* This does not work for subshells inside case statement                                                                               /* This does not work for subshells inside case statement
         command lists.  It's a suboptimal solution. */                                                                                          command lists.  It's a suboptimal solution. */
      else if (parser_state & PST_CASESTMT)     /* case statement pattern */                                                                  else if (parser_state & PST_CASESTMT)     /* case statement pattern */
        return " ";                                                                                                                             return " ";
      else                                                                                                                                    else
        return "; ";                            /* (...) subshell */                                                                            return "; ";                            /* (...) subshell */
    }                                                                                                                                       }
  else if (token_before_that == WORD && two_tokens_ago == FUNCTION)                                                                       else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
    return " ";         /* function def using `function name' without `()' */                                                               return " ";         /* function def using `function name' without `()' */

                                                                                                                                     >    /* If we're not in a here document, but we think we're about to parse one,
                                                                                                                                     >       and we would otherwise return a `;', return a newline to delimit the
                                                                                                                                     >       line with the here-doc delimiter */
                                                                                                                                     >    else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
                                                                                                                                     >      {
                                                                                                                                     >        last_was_heredoc = 1;
                                                                                                                                     >        return "\n";
                                                                                                                                     >      }
                                                                                                                                     >
  else if (token_before_that == WORD && two_tokens_ago == FOR)                                                                            else if (token_before_that == WORD && two_tokens_ago == FOR)
    {                                                                                                                                       {
      /* Tricky.  `for i\nin ...' should not have a semicolon, but                                                                            /* Tricky.  `for i\nin ...' should not have a semicolon, but
         `for i\ndo ...' should.  We do what we can. */                                                                                          `for i\ndo ...' should.  We do what we can. */
      for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)                                                         |        for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
        ;                                                                                                                                       ;
      if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')                                                  if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
        return " ";                                                                                                                             return " ";
      return ";";                                                                                                                             return ";";
    }                                                                                                                                       }
  else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))                                          else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
    return " ";                                                                                                                             return " ";

  for (i = 0; no_semi_successors[i]; i++)                                                                                                 for (i = 0; no_semi_successors[i]; i++)
    {                                                                                                                                       {
      if (token_before_that == no_semi_successors[i])                                                                                         if (token_before_that == no_semi_successors[i])
        return (" ");                                                                                                                           return (" ");
    }                                                                                                                                       }

  return ("; ");                                                                                                                          return ("; ");
}                                                                                                                                       }
#endif /* HISTORY */                                                                                                                    #endif /* HISTORY */

bashhist.c:

/* Add a line to the history list.                                                                                                      /* Add a line to the history list.
   The variable COMMAND_ORIENTED_HISTORY controls the style of history                                                                     The variable COMMAND_ORIENTED_HISTORY controls the style of history
   remembering;  when non-zero, and LINE is not the first line of a                                                                        remembering;  when non-zero, and LINE is not the first line of a
   complete parser construct, append LINE to the last history line instead                                                                 complete parser construct, append LINE to the last history line instead
   of adding it as a new line. */                                                                                                          of adding it as a new line. */
void                                                                                                                                    void
bash_add_history (line)                                                                                                                 bash_add_history (line)
     char *line;                                                                                                                             char *line;
{                                                                                                                                       {
  int add_it, offset, curlen;                                                                                                             int add_it, offset, curlen;
  HIST_ENTRY *current, *old;                                                                                                              HIST_ENTRY *current, *old;
  char *chars_to_add, *new_line;                                                                                                          char *chars_to_add, *new_line;

  add_it = 1;                                                                                                                             add_it = 1;
  if (command_oriented_history && current_command_line_count > 1)                                                                         if (command_oriented_history && current_command_line_count > 1)
    {                                                                                                                                       {
      chars_to_add = literal_history ? "\n" : history_delimiting_chars ();                                                           |        chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);

      using_history ();                                                                                                                       using_history ();
      current = previous_history ();                                                                                                          current = previous_history ();

      if (current)                                                                                                                            if (current)
        {                                                                                                                                       {
          /* If the previous line ended with an escaped newline (escaped                                                                          /* If the previous line ended with an escaped newline (escaped
             with backslash, but otherwise unquoted), then remove the quoted                                                                         with backslash, but otherwise unquoted), then remove the quoted
             newline, since that is what happens when the line is parsed. */                                                                         newline, since that is what happens when the line is parsed. */
          curlen = strlen (current->line);                                                                                                        curlen = strlen (current->line);

          if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&                                                                 if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
              current->line[curlen - 2] != '\\')                                                                                                      current->line[curlen - 2] != '\\')
            {                                                                                                                                       {
              current->line[curlen - 1] = '\0';                                                                                                       current->line[curlen - 1] = '\0';
              curlen--;                                                                                                                               curlen--;
              chars_to_add = "";                                                                                                                      chars_to_add = "";
            }                                                                                                                                       }

                                                                                                                                     >            /* If we're not in some kind of quoted construct, the current history
                                                                                                                                     >               entry ends with a newline, and we're going to add a semicolon,
                                                                                                                                     >               don't.  In some cases, it results in a syntax error (e.g., before
                                                                                                                                     >               a close brace), and it should not be needed. */
                                                                                                                                     >            if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
                                                                                                                                     >              chars_to_add++;
                                                                                                                                     >
          new_line = (char *)xmalloc (1                                                                                                           new_line = (char *)xmalloc (1
                                      + curlen                                                                                                                                + curlen
                                      + strlen (line)                                                                                                                         + strlen (line)
                                      + strlen (chars_to_add));                                                                                                               + strlen (chars_to_add));
          sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);                                                                        sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
          offset = where_history ();                                                                                                              offset = where_history ();
          old = replace_history_entry (offset, new_line, current->data);                                                                          old = replace_history_entry (offset, new_line, current->data);
          free (new_line);                                                                                                                        free (new_line);

          if (old)                                                                                                                                if (old)
            free_history_entry (old);                                                                                                               free_history_entry (old);

          add_it = 0;                                                                                                                             add_it = 0;
        }                                                                                                                                       }
    }                                                                                                                                       }

  if (add_it)                                                                                                                             if (add_it)
    really_add_history (line);                                                                                                              really_add_history (line);

                                                                                                                                     >  #if defined (SYSLOG_HISTORY)
                                                                                                                                     >    bash_syslog_history (line);
                                                                                                                                     >  #endif
                                                                                                                                     >
  using_history ();                                                                                                                       using_history ();
}                                                                                                                                       }

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .