Linux sort命令处理含连字符和冒号的字符串时失效如何解决?
多特殊字符场景下的字符串排序异常问题解决
现有相关问答仅覆盖单种特殊字符的排序场景,暂无专门讨论多种特殊字符共同导致排序异常的内容。
我的数据集同时包含连字符和冒号:连字符出现在字符串第一段,冒号作为排序的列分隔符,示例数据如下:
s3:GetObject ssm:GetParameter ssm:GetParameters ssm:GetParametersByPath secretsmanager:GetSecretValue cognito-identity:GetOpenIdToken cognito-identity:GetOpenIdTokenForDeveloperIdentity cognito-identity:GetCredentialsForIdentity connect:GetFederationToken ecr:GetAuthorizationToken gamelift:RequestUploadCredentials sts:GetFederationToken sts:GetSessionToken s3:GetObject secretsmanager:GetSecretValue ssm:GetParameter ssm:GetParameters ssm:GetParametersByPath
我需要执行sort | uniq或等效操作得到如下去重排序后的结果:
cognito-identity:GetCredentialsForIdentity cognito-identity:GetOpenIdToken cognito-identity:GetOpenIdTokenForDeveloperIdentity connect:GetFederationToken ecr:GetAuthorizationToken gamelift:RequestUploadCredentials s3:GetObject secretsmanager:GetSecretValue ssm:GetParameter ssm:GetParameters ssm:GetParametersByPath sts:GetFederationToken sts:GetSessionToken
但多次尝试均无法得到预期结果,试过的方案包括标准sort | uniq、sort -k 2,2 -t:、LC_COLLATE=C sort等变体,返回结果均严重乱序。比如| sort -u、LC_COLLATE=C sort甚至sort -k 1 -k 2 -t- | uniq都会得到类似如下的乱序结果:
cognito-identity:GetOpenIdToken s3:GetObject cognito-identity:GetCredentialsForIdentity ...
最接近预期的结果是使用| sort -k 2 -t- | uniq输出的内容:
s3:GetObject connect:GetFederationToken ecr:GetAuthorizationToken gamelift:RequestUploadCredentials secretsmanager:GetSecretValue ssm:GetParameter ssm:GetParameters ssm:GetParametersByPath sts:GetFederationToken sts:GetSessionToken cognito-identity:GetCredentialsForIdentity cognito-identity:GetOpenIdToken cognito-identity:GetOpenIdTokenForDeveloperIdentity
但仍和需求相差甚远,也查找过awk的替代方案,只要能解决问题都可接受。
编辑补充1
针对评论的疑问补充完整处理命令(使用了网友建议的LC_ALL=C cat -vet查看原始输出,该技巧非常实用):
cloudsplaining scan-policy-file --input-file $FILENAME.json | grep Actions | sed 's/Actions.*: //g' | tr ' ' '\n' | tr -d ',' | LC_ALL=C cat -vet
输出结果如下:
^[[1msecretsmanager:GetSecretValue$ ssm:GetParameter$ ssm:GetParametersByPath$ s3:GetObject$ ssm:GetParameters$ ^[[1mconnect:GetFederationToken$ gamelift:GetInstanceAccess$ cognito-identity:GetOpenIdTokenForDeveloperIdentity$ ec2:GetPasswordData$ sts:GetSessionToken$ cognito-idp:GetSigningCertificate$ cognito-identity:GetCredentialsForIdentity$ ecr:GetAuthorizationToken$ cognito-identity:GetOpenIdToken$ sts:GetFederationToken$ ^[[1ms3:GetObject$ secretsmanager:GetSecretValue$ ssm:GetParameter$ ssm:GetParameters$ ssm:GetParametersByPath$
可见输出中包含未知来源的垃圾控制字符,这正是导致排序异常的原因,询问该如何清理这些字符解决问题。
编辑补充2(已解决)
使用| LC_ALL=C cat -vet技巧查看原始输出后,定位到[[1m这类ANSI转义控制字符的来源,最终在sed匹配规则前加上.*匹配前缀所有字符就解决了问题,修改后的命令如下:
cloudsplaining scan-policy-file --input-file $FILENAME.json | grep Actions | sed 's/.*Actions.*: //g' | tr ' ' '\n' | tr -d ',' | LC_ALL=C cat -vet
修改后的输出结果如下:
secretsmanager:GetSecretValue$ ssm:GetParameters$ ssm:GetParametersByPath$ s3:GetObject$ ssm:GetParameter$ ec2:GetPasswordData$ cognito-identity:GetOpenIdTokenForDeveloperIdentity$ cognito-idp:GetSigningCertificate$ sts:GetFederationToken$ ecr:GetAuthorizationToken$ cognito-identity:GetCredentialsForIdentity$ gamelift:GetInstanceAccess$ cognito-identity:GetOpenIdToken$ connect:GetFederationToken$ sts:GetSessionToken$ s3:GetObject$ secretsmanager:GetSecretValue$ ssm:GetParameter$ ssm:GetParameters$ ssm:GetParametersByPath$
此时再执行| sort | uniq即可正常得到预期的去重排序结果,问题解决。
内容的提问来源于stack exchange,提问作者TryTryAgain
相关产品推荐
相关产品推荐

