Insert Control Characters in vi with Ctrl-V for Oracle Prompts
Insert Control Characters in vi with Ctrl-V for Oracle Prompts
Purpose
A custom SQL*Plus prompt that prints the connected instance name in colour, or a login script that clears the screen before the banner, both need one thing the keyboard cannot type directly: a literal control character embedded in the file. Press Esc while editing and vi leaves insert mode. Press Enter and vi opens a new line instead of writing a carriage return into the buffer. The control codes a terminal escape sequence is built from are exactly the keys vi reserves for its own commands, so typing them does the wrong thing.
Ctrl-V is the escape hatch. In vi insert mode, Ctrl-V tells the editor to take the next keystroke literally — to store its raw byte in the file rather than act on it. This is how a DBA embeds an Esc (^[, the start of every ANSI terminal sequence), a carriage return (^M), or a bell (^G) inside a glogin.sql, a .profile, or a shell wrapper without the keystroke being interpreted.
The technique is small but it unlocks a whole class of UNIX edits: coloured SQL*Plus prompts, scripts that reposition the cursor, and the repair of DOS line endings that sneak into files transferred from Windows. It works in classic vi, in vim, and at any shell prompt running in vi editing mode.
Code
1# In vi, enter insert mode first (press i), then:
2
3Ctrl-V Esc -> inserts a literal ESC character, shown as ^[
4Ctrl-V Enter -> inserts a literal carriage return, shown as ^M
5Ctrl-V Ctrl-G -> inserts a literal BEL (bell) character, shown as ^G
6Ctrl-V Ctrl-I -> inserts a literal TAB, shown as ^I
7
8# Example: a coloured SQL*Plus prompt in glogin.sql.
9# The ^[ below is a real ESC byte typed with Ctrl-V Esc, not the
10# two printable characters caret and open-bracket.
11
12SET SQLPROMPT "^[[1;33m_USER@_CONNECT_IDENTIFIER>^[[0m "
13
14# Example: strip trailing ^M (carriage returns) from a DOS-tainted
15# script, using a literal CR typed as Ctrl-V Ctrl-M in the search.
16:%s/^V^M//g
Code Breakdown
The mechanism is one keystroke with three roles, depending on what follows it.
Ctrl-V as the literal-next prefix
In insert mode, Ctrl-V (sometimes documented as Ctrl-Q on terminals where Ctrl-V is intercepted for flow control) suspends vi's normal key handling for one keystroke. The very next key is written to the buffer as its raw byte value. vi then displays that byte in caret notation: an Esc byte shows on screen as ^[, a carriage return as ^M, a tab as ^I. The caret form is a display convenience — the file holds a single non-printing byte, not the two visible characters.
The SQL*Plus prompt example
SET SQLPROMPT controls the text SQLPlus prints before every command. The string ^[[1;33m is an ANSI escape sequence: a real Esc byte (typed with Ctrl-V Esc), then [1;33m, which sets bold yellow. _USER and _CONNECT_IDENTIFIER are SQLPlus substitution variables that expand to the login name and the connect string. The trailing ^[[0m resets the colour so query output is not painted yellow too. Put this line in glogin.sql and every SQL*Plus session opens with a coloured, instance-aware prompt — a cheap guard against running a DROP on production when you meant the test database.
The search-and-replace example
:%s/^V^M//g is an ex substitution across the whole file. Inside the search pattern you again press Ctrl-V then Ctrl-M to enter a literal carriage return, so the pattern matches the stray ^M bytes that appear at the end of every line in a file edited on Windows and copied to UNIX. Replacing them with nothing converts DOS line endings to clean UNIX ones — a frequent fix when a SQL script uploaded by FTP in binary mode refuses to run cleanly.
Key Points
Ctrl-Vmeans "take the next key literally." It is the only portable way to put a control byte into a file from inside vi.- Caret notation is display-only.
^[on screen is oneEscbyte on disk, not a caret followed by a bracket. Counting characters by eye will mislead you. Ctrl-Qis the fallback. On sessions where the terminal eatsCtrl-Vfor XON/XOFF flow control, vi acceptsCtrl-Qfor the same literal-next behaviour.- The escape character starts every ANSI sequence. Coloured prompts, cursor moves, and screen clears all begin with a literal
Esc(^[), which is why this keystroke is the foundation for terminal-styling an Oracle login script. - A literal
^Mis a carriage return, not a newline. It is the visible symptom of DOS line endings, andCtrl-V Ctrl-Mis how you match and remove it.
Insights and Best Practices
Prefer named conventions where they exist
Modern vim also accepts Ctrl-V u followed by four hex digits to insert a Unicode code point, and Ctrl-V followed by three decimal digits to insert a byte by its decimal value — for example Ctrl-V 027 for Esc. The decimal form is unambiguous and survives copy-paste better than pressing an unprintable key, so it is the safer choice when you are documenting a procedure for a runbook.
Keep escape sequences out of shared scripts when you can
A glogin.sql that paints the prompt is convenient on your own terminal, but the embedded Esc bytes turn into garbage on a terminal that does not understand ANSI colour, and they can corrupt the output when SQL*Plus is driven by a calling program that captures stdout. Reserve coloured prompts for interactive login.sql files in your own home directory; keep automated and batch scripts free of control bytes.
Verify the byte, do not trust the eye
After inserting a control character, confirm it landed correctly with cat -v file or od -c file. cat -v renders the same caret notation vi shows, and od -c prints the exact byte values. Both let you prove an Esc is really 033 and not the literal text ^[.
Use this to repair, not just to create
The most common real-world use is cleanup: removing the ^M carriage returns that break a SQL script transferred from a Windows workstation, or stripping a stray bell character that makes a terminal beep every time a log is tailed. The Ctrl-V prefix is what lets you type the offending byte into a search pattern so it can be matched and deleted.
When to Use This
- Building a coloured or instance-aware SQL*Plus prompt in
glogin.sqlorlogin.sql. - Embedding a terminal escape sequence — clear screen, cursor move, colour — in a UNIX login or banner script.
- Removing DOS carriage returns (
^M) from a SQL or shell script copied from Windows. - Inserting a literal tab into a file where the editor would otherwise expand it to spaces.
- Stripping a stray control byte (bell, form feed) that is corrupting log output or a terminal session.
Troubleshooting Common Issues
If Ctrl-V seems to do nothing, the terminal is probably intercepting it before vi sees it — try Ctrl-Q instead, which most vi builds accept as the same literal-next prefix. If you typed the prompt sequence but the colour does not appear, you most likely typed the two printable characters ^ and [ rather than a real Esc; open the file with cat -v and confirm the ^[ is a single highlighted byte, then re-enter it with Ctrl-V Esc. If a script that ran on Windows now fails on UNIX with odd "command not found" errors at line ends, the cause is almost always trailing ^M bytes — run cat -v script.sql to confirm, then remove them with the :%s/^V^M//g substitution or with dos2unix if it is installed. When a coloured prompt corrupts the output of a batch job, remove the escape sequence from the shared script and keep it only in your interactive login file.
References
- vi — POSIX manual page (man7.org) — the standard reference for vi command and insert-mode behaviour, including the literal-next keystroke
- SQLPlus SET system variable summary — SQLPlus User's Guide 19c — documents SET SQLPROMPT and the substitution variables used in the coloured-prompt example
- stty — UNIX terminal line settings manual page (man7.org) — explains the flow-control characters that can intercept Ctrl-V and why Ctrl-Q is the fallback
- shutdownabort.com — Miscellaneous Useful UNIX (Wayback, 2013-01-15) — original DBA quick-reference page that recorded the control-character capture technique
Posts in this series
- List Files Opened by an Oracle Process with lsof -p
- Delete the 500 Oldest Files in a Directory (Oracle DBA)
- Diagnose Oracle Net and RAC Interconnect Routing with netstat -r
- Unpacking Oracle Patch and Install Media with cpio
- Oracle Export Through a Named Pipe with mknod for Space-Constrained Hosts
- Recursive find and grep to Search Oracle Trace Files for Any String
- Find the Biggest Files First When an Oracle Filesystem Fills Up
- Scan Every Oracle Alert and Trace Log for ORA- Errors with grep
- vi Editor Commands Reference for Oracle DBAs
- Disable vi Autoindent Before Pasting SQL Scripts on Oracle Hosts
- Enable vi Command-Line Editing in ksh for Oracle DBA Shells
- Search UNIX Man Pages for Oracle DBA Tools with man -k
- Insert Control Characters in vi with Ctrl-V for Oracle Prompts