Linux Shell开发中自定义uniq命令的输入输出处理疑问
自定义Shell版uniq命令:输入输出实现指南
核心前提:Shell中标准输入的本质
通过管道(如cat input.txt | your_uniq)或直接文件输入传递的内容,是流式的文本行序列,既不是单个字符串也不是数组。你的脚本需要逐行读取这些内容,再结合已实现的算法处理。
第一步:逐行读取输入的Shell实现
用while read循环是处理流式输入的标准方式,能正确保留每行的格式(包括空格、空行):
while IFS= read -r line; do # 在这里对每一行$line执行你的逻辑 done
IFS=:避免行首/行尾的空格被截断-r:禁止解析转义字符,保证原始内容被读取
第二步:结合算法实现两种模式
基于你的去重计数算法,我们可以通过变量维护当前行内容和计数,再根据参数判断输出模式:
完整示例脚本(my_uniq.sh)
#!/bin/bash # 初始化状态变量 count=1 prev_line="" count_mode=0 # 解析参数:判断是否开启计数模式 if [ "$1" = "-c" ]; then count_mode=1 # 处理文件输入(如果指定) input_source="${2:-/dev/stdin}" else input_source="${1:-/dev/stdin}" fi # 逐行处理输入 while IFS= read -r line; do if [ -z "$prev_line" ]; then # 读取第一行,初始化基准行 prev_line="$line" else if [ "$line" = "$prev_line" ]; then # 当前行与基准行相同,计数+1 ((count++)) else # 当前行与基准行不同,输出基准行结果 if [ $count_mode -eq 1 ]; then printf "%d %s\n" "$count" "$prev_line" else printf "%s\n" "$prev_line" fi # 重置基准行和计数 prev_line="$line" count=1 fi fi done < "$input_source" # 处理最后一行(循环结束后剩余的基准行) if [ -n "$prev_line" ]; then if [ $count_mode -eq 1 ]; then printf "%d %s\n" "$count" "$prev_line" else printf "%s\n" "$prev_line" fi fi
第三步:测试与使用
- 给脚本添加执行权限:
chmod +x my_uniq.sh
- 普通模式测试(输出唯一行):
$ cat input.txt | ./my_uniq.sh Cinnamon Egg Flour Milk
- 计数模式测试(输出行+出现次数):
$ cat input.txt | ./my_uniq.sh -c 1 Cinnamon 2 Egg 3 Flour 2 Milk
- 直接读取文件的方式:
# 普通模式 ./my_uniq.sh input.txt # 计数模式 ./my_uniq.sh -c input.txt
关键细节补充
- 空行处理:脚本会正确保留并统计空行(符合原生uniq的行为)
- 行内容区分:严格比较每行的完整内容(包括空格、制表符),与原生uniq一致
- 兼容性:支持所有类Unix Shell环境(bash、zsh等)
内容的提问来源于stack exchange,提问作者ihatec
相关产品推荐
相关产品推荐

