-
-
Notifications
You must be signed in to change notification settings - Fork 710
Description
Problem / Use Case
When using --output-format=shell (or -o=shell), yq collapses nested keys using a single underscore _ as the separator. For example:
my_app:
database_config:
host: localhostbecomes:
my_app_database_config_host=localhostThis creates ambiguity when the original YAML keys themselves contain underscores. It's impossible to distinguish between:
- A nested structure like
my.app.database(3 keys) - A flat structure like
my_app.database(2 keys, where first key contains_) - A single key like
my_app_database(1 key)
This is particularly problematic when:
- Working with YAML files that use snake_case naming conventions
- Sourcing the shell variables and then trying to reconstruct the original YAML structure
- Using the shell output in scripts that need to parse the variable names
Proposed Solution
Add a --shell-key-separator flag (similar to existing --properties-separator and --csv-separator flags) that allows users to specify a custom separator for collapsing nested keys in shell output format.
Default behavior: _ (single underscore) - maintains backward compatibility
Example usage:
yq -o=shell --shell-key-separator="__" file.yamlExamples
Given sample.yml:
my_app:
db_config:
host: localhost
port: 5432Current behavior (yq -o=shell sample.yml):
my_app_db_config_host=localhost
my_app_db_config_port=5432Problem: Three underscores - hard to tell where the original key boundaries are
Proposed behavior (yq -o=shell --shell-key-separator="__" sample.yml):
my_app__db_config__host=localhost
my_app__db_config__port=5432Clear: Double underscores indicate nesting, single underscores are part of the original key names
Implementation Notes
Following the pattern of similar flags in yq:
-
Add ShellVariablesPreferences struct (similar to
PropertiesPreferences,CSVPreferences, etc.):type ShellVariablesPreferences struct { KeySeparator string } func NewDefaultShellVariablesPreferences() ShellVariablesPreferences { return ShellVariablesPreferences{ KeySeparator: "_", } } var ConfiguredShellVariablesPreferences = NewDefaultShellVariablesPreferences()
-
Update shellVariablesEncoder to accept preferences:
func NewShellVariablesEncoder() Encoder { return &shellVariablesEncoder{ prefs: ConfiguredShellVariablesPreferences, } }
-
Update appendPath function (line 129 in
encoder_shellvariables.go):// Current: return cookedPath + "_" + key // Proposed: return cookedPath + pe.prefs.KeySeparator + key
-
Add CLI flag in
cmd/root.go:rootCmd.PersistentFlags().StringVar( &yqlib.ConfiguredShellVariablesPreferences.KeySeparator, "shell-key-separator", yqlib.ConfiguredShellVariablesPreferences.KeySeparator, "separator for shell variable key paths", )
Backward Compatibility
✅ Fully backward compatible - default value of _ maintains existing behavior
Related Flags
This follows the same pattern as existing separator flags:
--properties-separator- separator between keys and values in properties format (default" = ")--csv-separator- CSV separator character (default,)
Validation Considerations
The separator should be validated to ensure it produces valid shell variable names:
- Must only contain characters allowed in shell variable names:
[a-zA-Z0-9_] - Should not be empty
- Suggested validation in
Set()method or when flag is parsed
Additional Benefits
This flag would also help when:
- Generating shell variables for consumption by other tools expecting specific naming conventions
- Working with configuration management systems that have their own naming standards
- Debugging - easier to visually parse variable names with custom separators