I have the following string blob in Go:
AWS_FIREHOSE_US_WEST_2_ENDPOINT: https://foobar.firehose.us-west-2.amazonaws.com
BOT_NAME: mybot
DEV_MODE: false
GITHUB_APP_ID: 1234
GITHUB_INSTALLATION_ID: 1234
GITHUB_ORG_NAME: myorg
SERVICE_WHO_IS_WHO_DEFAULT_HOST: foo.bar
SERVICE_WHO_IS_WHO_DEFAULT_PORT: 80
SERVICE_WHO_IS_WHO_DEFAULT_PROTO: http
TZ: UTC
_APP_NAME: myapp
_BUILD_ID: 12345
_DEPLOYMENT_ID: dev--foo.d53
_DEPLOY_ENV: dev
_OTEL_COLLECTOR_URL: tcp://localhost:4317
_POD_ACCOUNT: 12345
_POD_ID: a6127c9c-2be8-4078-8c00-132d29fbecfc
_POD_REGION: us-west-1
_POD_SHORTNAME: us-west-1-dev-default
_TEAM_OWNER: eng-infra
_TRACING_ENABLED: false
force_restart: 2024-01-02T19:00:59Z
GITHUB_PRIVATE_KEY: -----BEGIN RSA PRIVATE KEY-----
fofofofofofofofofofofofofofoofofofofofofofofofoffof
barbabaabababababababababababababababababaababababa
batbababtbabttbtbabtbtabtbtbtbtbtbabtbtbbtbtbtbttbt
-----END RSA PRIVATE KEY-----
This is a single string in Golang, separated by "\n", so please notice, it's not sorted by the key: value
pair. I need to sort it out by the primary key, what would be the best way to accomplish this?
I've tried the following method:
// sortLines sorts the lines in a blob of text.
func sortLines(blob string) string {
var sorted sort.StringSlice
sorted = strings.Split(blob, "\n")
sorted.Sort()
return strings.Join(sorted, "\n")
}
Please notice trying to sort by line won't work due to the fact the GITHUB_PRIVATE_KEY:
contains multiple lines.
EDIT: Revised to handle all forms of ASCII Armor.
Your string is not a blob. It has a well-defined structure. It contains an ASCII Armor value:
GITHUB_PRIVATE_KEY: -----BEGIN RSA PRIVATE KEY-----
fofofofofofofofofofofofofofoofofofofofofofofofoffof
barbabaabababababababababababababababababaababababa
batbababtbabttbtbabtbtabtbtbtbtbtbabtbtbbtbtbtbttbt
-----END RSA PRIVATE KEY-----
6.6. Example of an ASCII Armored Message
-----BEGIN PGP MESSAGE----- Version: OpenPrivacy 0.99add ASCII Armor example to test data yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS vBSFjNSiVHsuAA== =njUN -----END PGP MESSAGE-----
A case insensitive sort (insert ASCII Armor example into test data):
AWS_FIREHOSE_US_WEST_2_ENDPOINT: https://foobar.firehose.us-west-2.amazonaws.com
BOT_NAME: mybot
DEV_MODE: false
force_restart: 2024-01-02T19:00:59Z
GITHUB_APP_ID: 1234
GITHUB_INSTALLATION_ID: 1234
GITHUB_ORG_NAME: myorg
GITHUB_PRIVATE_KEY: -----BEGIN RSA PRIVATE KEY-----
fofofofofofofofofofofofofofoofofofofofofofofofoffof
barbabaabababababababababababababababababaababababa
batbababtbabttbtbabtbtabtbtbtbtbtbabtbtbbtbtbtbttbt
-----END RSA PRIVATE KEY-----
IETF_RFC4880_ASCII_ARMOR_EXAMPLE: -----BEGIN PGP MESSAGE-----
Version: OpenPrivacy 0.99
yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
vBSFjNSiVHsuAA==
=njUN
-----END PGP MESSAGE-----
SERVICE_WHO_IS_WHO_DEFAULT_HOST: foo.bar
SERVICE_WHO_IS_WHO_DEFAULT_PORT: 80
SERVICE_WHO_IS_WHO_DEFAULT_PROTO: http
TZ: UTC
_APP_NAME: myapp
_BUILD_ID: 12345
_DEPLOYMENT_ID: dev--foo.d53
_DEPLOY_ENV: dev
_OTEL_COLLECTOR_URL: tcp://localhost:4317
_POD_ACCOUNT: 12345
_POD_ID: a6127c9c-2be8-4078-8c00-132d29fbecfc
_POD_REGION: us-west-1
_POD_SHORTNAME: us-west-1-dev-default
_TEAM_OWNER: eng-infra
_TRACING_ENABLED: false
https://go.dev/play/p/B3x_AbAvZHs
func sortConfig(config string) (string, error) {
type KL struct {
key, lines string
}
var kls []KL
scnr := bufio.NewScanner(strings.NewReader(config))
inArmor := false // ASCII Armor (IETF RFC4880)
for scnr.Scan() {
line := scnr.Text() + "\n"
if inArmor {
kls[len(kls)-1].lines += line
armor := strings.TrimSpace(line)
inArmor = !strings.HasPrefix(armor, "-----END ") ||
!strings.HasSuffix(armor, "-----")
continue
}
if len(strings.TrimSpace(line)) == 0 {
continue
}
key, value, pair := strings.Cut(line, ":")
if !pair {
key, value = "", key
}
if pair {
armor := strings.TrimSpace(value)
inArmor = strings.HasPrefix(armor, "-----BEGIN ") &&
strings.HasSuffix(armor, "-----")
}
key = strings.TrimSpace(key)
key = strings.ToUpper(key) // case insensitive
kls = append(kls, KL{key: key, lines: line})
}
if err := scnr.Err(); err != nil {
return "", err
}
slices.SortStableFunc(kls, func(a, b KL) int {
return cmp.Compare(a.key, b.key)
})
var b strings.Builder
b.Grow(len(config))
for _, kl := range kls {
b.WriteString(kl.lines)
}
return b.String(), nil
}