Editing Content Advanced
Beyond single-cell edits, VisiData supports regex-based bulk replace, incremental value generation, macros for repeated workflows, and CommandLog editing for precise replay control.
Focus on regex replace (*) for pattern-based data cleaning and incremental columns (i) for generating sequences — two of the most time-saving bulk editing operations.
Regex Replace on a Column
Use * to create a derived column that replaces a pattern with a new value (non-destructive):
* search<Tab>replace create new column replacing regex with text
g* search<Tab>replace modify current column for all selected rows (in-place)
gz* search<Tab>replace modify all visible columns for selected rows
Example — normalize status values:
# Move to 'status' column
g*
# Enter: active<Tab>ACTIVE
# All 'active' cells in 'status' become 'ACTIVE' for selected rows
Example — strip port from hostname:
# Move to 'endpoint' column
*
# Enter: :\d+<Tab>
# Creates new column without port numbers: host:8080 → host
Incremental Values
i add column with incremental integer values (1, 2, 3...)
gi set current column for selected rows to incremental values
zi <step> add column with values at given increment step
gzi <step> set current column for selected rows at given step
Example — add a row ID column:
# Move to leftmost position
i
# Name it: row_id
# A new column appears: 1, 2, 3, 4...
Macros
Macros record a sequence of keystrokes and replay them with a single key.
m <keystroke> start recording macro; press same key again to stop
gm open Macro Index (view all recorded macros)
Example — create a macro to frequency-table the current column and return:
m f # start recording, bound to 'f'
Shift+F # open frequency table
q # return to source sheet
m f # stop recording
# Now pressing f will do: Shift+F then q
Macros override existing keybindings. Use uncommon keys (e.g., function keys or uppercase letters that are not already used) to avoid conflicts.
CommandLog Editing (Shift+D)
The CommandLog records every action taken in VisiData as a replayable .vdj file.
Shift+D # open CommandLog for current sheet
gD # open global CommandLog (all commands)
zD # open CommandLog with parent sheet commands removed
# Inside CommandLog:
x # replay command at current row
gx # replay entire CommandLog
^C # abort replay
Ctrl+S # save CommandLog to .vdj file
Use case — document a data cleaning workflow:
# Perform your data cleaning steps interactively
# Press Shift+D to view the recorded commands
# Press Ctrl+S → save as /tmp/clean_workflow.vdj
# Later, replay on a new file:
vd --play clean_workflow.vdj --batch newfile.csv -o cleaned.csv
Joining / Appending Sheets
& append/merge top two sheets in the sheet stack
g& append ALL sheets in the stack
Join types available when prompted:
| Type | Behavior |
|---|---|
inner | Keep only rows matching keys on ALL sheets |
outer | Keep all rows from first sheet |
full | Keep all rows from all sheets (union) |
diff | Keep rows NOT in all sheets |
append | Combine all rows from all sheets |
extend | Copy first sheet, extend with columns from others |
merge | All rows from first, update empty cells from second |
Transposing a Sheet
T open a transposed sheet (rows become columns)
Useful for wide datasets where columns represent time periods.
Practical Use Cases
Normalize Status Labels
vd /tmp/servers.csv
gs # select all rows
g*
# Enter: standby<Tab>STANDBY
# All 'standby' values → 'STANDBY' for selected rows
Generate Row IDs for Import
vd /tmp/data.csv
# Move cursor to first column
i
# Name: id
# Rows now have sequential IDs: 1, 2, 3, ...
Ctrl+S
# Save as: /tmp/data_with_ids.csv
Document and Replay Data Cleaning
# Open source file
vd /var/www/html/exports/raw_orders.csv
# Perform cleaning steps interactively:
# 1. Cast 'amount' to float: move cursor, press %
# 2. Delete null rows: z| amount is None → gd
# 3. Rename 'amt' column to 'amount'
# Save CommandLog
Shift+D
Ctrl+S
# Save as: /tmp/clean_orders.vdj
# Replay next time:
vd --play /tmp/clean_orders.vdj --batch new_orders.csv -o cleaned_orders.csv
Troubleshooting Matrix
| Problem | Cause | Fix |
|---|---|---|
| Regex replace matches nothing | Regex doesn't match | Test regex with / search first |
i creates column at wrong position | Cursor on wrong column | Move cursor left first |
| Macro conflicts with existing key | Key already bound | Use gm to check, choose different key |
| CommandLog replay fails | Sheet structure changed | Re-record from scratch |
Hands-On Practice
vd /tmp/servers.csv
# 1. gs → select all
# 2. g* → type: active<Tab>ACTIVE → confirm
# 3. Press U to undo
# 4. Press i → add incremental ID column named 'id'
# 5. Press Shift+D → view recorded commands
# 6. Press q → return to sheet
# 7. Press Ctrl+S → save as /tmp/servers_advanced.csv