Terminal emulators such as
gnome-terminal ("Terminal" in Ubuntu) but also
urxvt are named "emulators" because they reproduce the behavior of older terminals which were the only display of a computer. Such terminals communicated with the computer with a text-based protocol and were initially designed to receive only text. Quickly, more control was needed: how to erase a line? Use colors? Or change the cursor position?
Source: The Art of Unix Usability - Command-Line Interfaces
Escape sequences were designed for every terminal to do such things. They are named escape because they start with the ASCII escape code:
33. There's no way to print such a character directly, which makes it a good fit for such sequences. When we still want to display this characted,
^[[ is used, and this is what I'll use in my explanations.
When the terminal received
^[[A, it did not mean "print ^[[A", but "the user pressed the up-arrow key". "A" here is totally arbitrary: it just happens to be the letter everybody agreed on, because that's what the DEC VT-52 and its successor the popular VT-100 terminal used.
Source: DEC VT-52 Maintenance Manual 1976
This is still the way terminal emulators work today: depending on the
$TERM variable, a database named
terminfo is responsible for saying what codes should be sent to the shell (bash, sh, zsh...), which is then responsible for understanding them and react to them.
Now, the code for Shift + up happens to be
^[[1;2A: the terminal emulator sends this code to the shell, which tries to interpret
^[[1;2 but does not display anything because it doesn't know about that escape sequence. But
A is left and displayed.