Linux Bash中实现排序去重及特殊输出规则的方法
没问题,咱们可以用Bash的数组和循环来完美实现这个需求,下面是完整的实现方案,我会一步步拆解说明:
完整Bash脚本实现
#!/bin/bash # 示例输入(你可以替换为从文件读取或管道输入) input=( "test1@gmail.com" "test2@gmail.com" "test1@hotmail.com" "test3@gmail.com" "test2@hotmail.com" "test3@hotmail.com" "test1@live.com" "test2@live.com" ) # 第一步:升序排序并去除重复行 sorted_unique=($(printf "%s\n" "${input[@]}" | sort -u)) # 第二步:将行分为两个数组:不含"gmail"的行 和 含"gmail"的行 non_gmail=() gmail=() for line in "${sorted_unique[@]}"; do if [[ "$line" != *"gmail"* ]]; then non_gmail+=("$line") else gmail+=("$line") fi done # 第三步:按规则交替输出 non_idx=0 gmail_idx=0 total_non=${#non_gmail[@]} total_gmail=${#gmail[@]} # 优先交替输出2条非gmail + 1条gmail,直到非gmail行耗尽 while [[ $non_idx -lt $total_non ]]; do # 输出最多2条非gmail行(处理最后剩余不足2条的情况) for ((i=0; i<2 && non_idx < total_non; i++)); do echo "${non_gmail[$non_idx]}" ((non_idx++)) done # 如果还有gmail行,输出1条 if [[ $gmail_idx -lt $total_gmail ]]; then echo "${gmail[$gmail_idx]}" ((gmail_idx++)) fi done # 输出剩余的gmail行(已提前排序,直接按字母序输出即可) while [[ $gmail_idx -lt $total_gmail ]]; do echo "${gmail[$gmail_idx]}" ((gmail_idx++)) done
关键步骤说明
1. 输入处理与去重排序
用printf "%s\n" "${input[@]}" | sort -u将输入内容按行展开,再通过sort -u完成升序排序+去重的组合操作。如果你的输入来自文件,只需替换成:
sorted_unique=($(sort -u your_input_file.txt))
如果是从管道接收输入(比如cat file.txt | ./your_script.sh),可以改成:
sorted_unique=($(sort -u))
2. 行分类逻辑
通过Bash的模式匹配[[ "$line" != *"gmail"* ]]判断每行是否包含"gmail"子串,分别存入两个数组,方便后续按规则输出。
3. 交替输出逻辑
- 用
non_idx和gmail_idx两个索引变量跟踪两个数组的当前输出位置; - 外层循环持续到所有非gmail行输出完毕,每次循环先输出最多2条非gmail行(避免最后剩余不足2条的边界情况),再输出1条gmail行;
- 当非gmail行耗尽后,直接输出剩余的gmail行即可——因为之前已经做过全局排序,剩余的gmail行本身就是按字母序排列的,完全符合需求。
测试结果
运行上述脚本,会得到你期望的输出:
test1@hotmail.com
test2@hotmail.com
test1@gmail.com
test3@hotmail.com
test1@live.com
test2@gmail.com
test2@live.com
test3@gmail.com
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

