Add --shell-key-separator flag for customizable shell output format

- Add ShellVariablesPreferences struct with KeySeparator field (default: '_')
- Update shellVariablesEncoder to use configurable separator
- Add --shell-key-separator CLI flag
- Add comprehensive tests for custom separator functionality
- Update documentation with example usage for custom separator

This feature allows users to specify a custom separator (e.g. '__') when
outputting shell variables, which helps disambiguate nested keys from
keys that contain underscores in their names.

Example:
  yq -o=shell --shell-key-separator='__' file.yaml

Fixes ambiguity when original YAML keys contain underscores.
This commit is contained in:
Robert Lee
2025-11-07 20:02:58 +11:00
committed by Mike Farah
parent 1228bcfa75
commit 1f2b0fe76b
6 changed files with 125 additions and 8 deletions
+44
View File
@@ -91,3 +91,47 @@ func TestShellVariablesEncoderEmptyMap(t *testing.T) {
func TestShellVariablesEncoderScalarNode(t *testing.T) {
assertEncodesTo(t, "some string", "value='some string'")
}
func assertEncodesToWithSeparator(t *testing.T, yaml string, shellvars string, separator string) {
var output bytes.Buffer
writer := bufio.NewWriter(&output)
// Save the original separator
originalSeparator := ConfiguredShellVariablesPreferences.KeySeparator
defer func() {
ConfiguredShellVariablesPreferences.KeySeparator = originalSeparator
}()
// Set the custom separator
ConfiguredShellVariablesPreferences.KeySeparator = separator
var encoder = NewShellVariablesEncoder()
inputs, err := readDocuments(strings.NewReader(yaml), "test.yml", 0, NewYamlDecoder(ConfiguredYamlPreferences))
if err != nil {
panic(err)
}
node := inputs.Front().Value.(*CandidateNode)
err = encoder.Encode(writer, node)
if err != nil {
panic(err)
}
writer.Flush()
test.AssertResult(t, shellvars, strings.TrimSuffix(output.String(), "\n"))
}
func TestShellVariablesEncoderCustomSeparator(t *testing.T) {
assertEncodesToWithSeparator(t, "a:\n b: Lewis\n c: Carroll", "a__b=Lewis\na__c=Carroll", "__")
}
func TestShellVariablesEncoderCustomSeparatorNested(t *testing.T) {
assertEncodesToWithSeparator(t, "my_app:\n db_config:\n host: localhost", "my_app__db_config__host=localhost", "__")
}
func TestShellVariablesEncoderCustomSeparatorArray(t *testing.T) {
assertEncodesToWithSeparator(t, "a: [{n: Alice}, {n: Bob}]", "a__0__n=Alice\na__1__n=Bob", "__")
}
func TestShellVariablesEncoderCustomSeparatorSingleChar(t *testing.T) {
assertEncodesToWithSeparator(t, "a:\n b: value", "aXb=value", "X")
}