keepcalculator

06 Numbers and Powers

Sed Replace Standalone YAML Key: Exact Match

Card No. 06·31432 · Updated · Standard formula, shown below

To replace only a standalone YAML key with sed, you anchor the pattern to the start of the line and the key name to the colon that follows it, like sed -i '/^key:/c\key: newvalue' file.yml. This ensures the replacement applies only when the key appears at the beginning of a line as its own YAML mapping entry, not as part of a nested key or a value elsewhere in the file.

Why a Plain sed Substitution Fails

A naive command such as sed 's/key/newkey/' file.yml will match key anywhere in a line. In a YAML file, the word key might appear inside a string value, as a substring of another key (e.g., monkey), or as part of a nested mapping like parent:
child: key
. Without anchoring, you risk corrupting data that was never meant to change.

YAML keys are defined by their position: they start at the beginning of a line (possibly after indentation) and are followed by a colon and a space (or end-of-line). A standalone key is one that appears at the top level of the document or at a specific indentation level you intend to target. The sed pattern must reflect that structure.

Anchoring to the Start of the Line

The caret ^ anchors the pattern to the beginning of the line. For a top-level key, the pattern is simply ^key:. To replace the whole line including the value, use the change command:

sed -i '/^key:/c\key: newvalue' file.yml

This finds any line that starts with key: and replaces the entire line with key: newvalue. If the key is indented (nested inside another mapping), you must include the leading spaces in the pattern. For example, to replace a key indented by two spaces:

sed -i '/^  key:/c\  key: newvalue' file.yml

Note that the backslash before the newline in the replacement is required in GNU sed to treat the replacement as a literal line. In BSD sed (macOS), the syntax differs slightly: you may need to use sed -i '' '/^key:/c\'$'\nkey: newvalue' file or simply use a substitution with a captured group.

Using Substitution with Word Boundaries

If you prefer to keep the value and only change the key name, use a substitution with a word boundary. GNU sed supports \b:

sed -i 's/^key\b/newkey/' file.yml

The \b ensures that key is not part of a longer word like monkey. Combined with the start-of-line anchor, this matches only when key is the first word on the line. However, this still matches key in a line like key: some value and also key alone (which is not valid YAML). To be strict, include the colon:

sed -i 's/^key:/newkey:/' file.yml

This replaces only the key name, leaving the value intact. The colon is a literal character that must be present immediately after the key name.

Handling Nested Keys and Indentation

YAML uses indentation to denote structure. A key at a deeper level has leading spaces. To replace a standalone key at a specific depth, you must match those spaces exactly. For example, given:

parent:
  child: old
  other: value

To change child to renamed, use:

sed -i '/^  child:/c\  renamed: newvalue' file.yml

If you want to match any indentation level, you can use a pattern that allows zero or more spaces, but be careful: that will also match top-level keys. A common approach is to use a capture group for the indentation:

sed -i 's/^\( *\)child:/\1renamed:/' file.yml

This preserves the original indentation and replaces only the key name. The \( *\) captures zero or more spaces, and the backreference \1 reinserts them.

Common Pitfalls and Misconceptions

One frequent mistake is forgetting that YAML allows flow-style mappings, such as {key: value} on a single line. A standalone key in block style is what most people mean, but if your file uses flow style, a line-based sed command will not work reliably. In that case, consider using a proper YAML parser like yq or a scripting language.

Another misconception is that sed can handle multi-line values. If a key’s value spans multiple lines (using a block scalar with | or >), the change command will only replace the first line, leaving the rest orphaned. For example:

key: |
  line1
  line2

Running sed '/^key:/c\key: new' will produce:

key: new
  line1
  line2

which is invalid YAML. In such cases, you need a more sophisticated tool or a multi-line sed script that deletes until the indentation drops.

Also, be aware that sed -i creates a temporary file and renames it, which changes file permissions. If you need to preserve permissions, use sed ... file > tmp && mv tmp file and then restore permissions manually.

Alternatives to sed for YAML Editing

While sed is a powerful stream editor, it is not YAML-aware. For complex files or when you need to preserve comments, quoting, and multi-line values, a dedicated YAML tool is safer. yq (a YAML processor) allows you to set a key with a simple expression:

yq -i '.key = "newvalue"' file.yml

This updates the key regardless of its position in the document, and it properly handles YAML syntax. Similarly, python with pyyaml can load, modify, and dump the file, but it will reorder keys and lose comments. For one-off edits, sed is fine if you understand its limitations.

Frequently Asked Questions

How do I replace a key only if it has a specific value?

Use a pattern that includes the value. For example, to change key: old to key: new, use sed -i 's/^key: old$/key: new/' file.yml. The $ anchors to the end of the line, ensuring the entire line is exactly that.

Can I replace a key in all files in a directory?

Yes, combine sed with a loop: for f in *.yml; do sed -i '/^key:/c\key: new' "$f"; done. Be careful to test on a backup first.

What if my key contains special characters like dots or dashes?

In sed patterns, a dot matches any character, so escape it with a backslash. For a key like app.name, use sed -i '/^app\.name:/c\app.name: new' file.yml. Dashes are literal, so no escaping needed.

Does sed work on Windows?

Yes, if you use a Unix-like environment such as Git Bash, WSL, or Cygwin. The syntax is the same, but line endings may need attention. Use sed -i 's/\r$//' to strip carriage returns if you encounter issues.

Why did my replacement change a substring inside a value?

Because your pattern did not include the start-of-line anchor and the colon. Always use ^key: to target the key definition, not just the word anywhere.

Is there a way to preview changes without editing?

Yes, omit the -i flag. sed '/^key:/c\key: new' file.yml prints the modified content to stdout without changing the file. Review it, then rerun with -i.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →