You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux Bash:按特殊字符优先排序指定子串的实现方案

问题

我需要对输入文件按第8个“/”后的子串(即“svc...”开头的部分)排序,且该子串内需按以下优先级排序:1. 字符“:”,2. 字符“/”,3. 字母字符。请问如何用sort命令或其他方法实现?

输入文件:

/path1/path2/path3/path4/path5/path6/ser/svcba/log:
/path1/path2/path3/path4/path5/path6/ser/svcba:
/path1/path2/path3/path4/path5/path6/ser/svcbb/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc:
/path1/path2/path3/path4/path5/path6/ser/svcb/log: 
/path1/path2/path3/path4/path5/path6/ser/svcb:
/path1/path2/path3/path4/path5/path6/ser/svca/log: 
/path1/path2/path3/path4/path5/path6/ser/svca:
/path1/path2/path3/path4/path5/path6/ser/svcbb:

期望输出:

/path1/path2/path3/path4/path5/path6/ser/svca:
/path1/path2/path3/path4/path5/path6/ser/svca/log: 
/path1/path2/path3/path4/path5/path6/ser/svcb:
/path1/path2/path3/path4/path5/path6/ser/svcb/log: 
/path1/path2/path3/path4/path5/path6/ser/svcba:
/path1/path2/path3/path4/path5/path6/ser/svcba/log:
/path1/path2/path3/path4/path5/path6/ser/svcbb:
/path1/path2/path3/path4/path5/path6/ser/svcbb/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc:
/path1/path2/path3/path4/path5/path6/ser/svcbc/log:

已尝试但未达预期的命令:

# 直接sort,带/log的行排在不带的前面,不符合需求
cat input.txt | sort
/path1/path2/path3/path4/path5/path6/ser/svca/log: 
/path1/path2/path3/path4/path5/path6/ser/svca:
/path1/path2/path3/path4/path5/path6/ser/svcba/log:
/path1/path2/path3/path4/path5/path6/ser/svcba: 
/path1/path2/path3/path4/path5/path6/ser/svcbb/log:
/path1/path2/path3/path4/path5/path6/ser/svcbb: 
/path1/path2/path3/path4/path5/path6/ser/svcbc/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc: 
/path1/path2/path3/path4/path5/path6/ser/svcb/log: 
/path1/path2/path3/path4/path5/path6/ser/svcb:

# 以:为分隔符排序,svcb/log的位置错误
cat input.txt | sort -t : -k 1,1
/path1/path2/path3/path4/path5/path6/ser/svca:
/path1/path2/path3/path4/path5/path6/ser/svca/log: 
/path1/path2/path3/path4/path5/path6/ser/svcb:
/path1/path2/path3/path4/path5/path6/ser/svcba:
/path1/path2/path3/path4/path5/path6/ser/svcba/log:
/path1/path2/path3/path4/path5/path6/ser/svcbb:
/path1/path2/path3/path4/path5/path6/ser/svcbb/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc:
/path1/path2/path3/path4/path5/path6/ser/svcbc/log:
/path1/path2/path3/path4/path5/path6/ser/svcb/log: 

# 以/为分隔符取第9段排序,带/log的行仍排在前面
cat input.txt | sort -t / -k 9,9  
/path1/path2/path3/path4/path5/path6/ser/svca/log: 
/path1/path2/path3/path4/path5/path6/ser/svca:
/path1/path2/path3/path4/path5/path6/ser/svcb/log: 
/path1/path2/path3/path4/path5/path6/ser/svcba/log:
/path1/path2/path3/path4/path5/path6/ser/svcba: 
/path1/path2/path3/path4/path5/path6/ser/svcbb/log:
/path1/path2/path3/path4/path5/path6/ser/svcbb: 
/path1/path2/path3/path4/path5/path6/ser/svcbc/log:
/path1/path2/path3/path4/path5/path6/ser/svcbc: 
/path1/path2/path3/path4/path5/path6/ser/svcb: 
解决方案

可以通过awk预处理生成自定义排序键,再结合sort实现需求,具体命令如下:

awk -F '/' '{key=$9; gsub(/:/, "\x01", key); gsub(/\//, "\x02", key); print key "\t" $0}' input.txt | sort | cut -f2-

命令解释:

  1. awk部分:

    • -F '/':以/作为字段分隔符,第8个/后的内容对应第9个字段$9
    • gsub(/:/, "\x01", key):把排序键中的:替换成ASCII值为1的控制字符(该字符比/和所有字母的ASCII值都小,排序时会排在最前)
    • gsub(/\//, "\x02", key):把排序键中的/替换成ASCII值为2的控制字符(比字母小,比\x01大,排序时排在:之后、字母之前)
    • print key "\t" $0:将自定义排序键和原行内容用制表符分隔输出
  2. sort:对awk输出的内容按排序键进行字典序排序,此时:对应的\x01会优先于/对应的\x02,最后是字母

  3. cut -f2-:去掉前面的自定义排序键,只保留原行内容,得到最终的排序结果

执行该命令后,输出将与你期望的结果完全一致。


内容的提问来源于Stack Exchange,提问作者wasilis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:19:54