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

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

第三步:测试与使用

  1. 给脚本添加执行权限:
chmod +x my_uniq.sh
  1. 普通模式测试(输出唯一行):
$ cat input.txt | ./my_uniq.sh
Cinnamon
Egg
Flour
Milk
  1. 计数模式测试(输出行+出现次数):
$ cat input.txt | ./my_uniq.sh -c
1 Cinnamon
2 Egg
3 Flour
2 Milk
  1. 直接读取文件的方式:
# 普通模式
./my_uniq.sh input.txt

# 计数模式
./my_uniq.sh -c input.txt

关键细节补充

  • 空行处理:脚本会正确保留并统计空行(符合原生uniq的行为)
  • 行内容区分:严格比较每行的完整内容(包括空格、制表符),与原生uniq一致
  • 兼容性:支持所有类Unix Shell环境(bash、zsh等)

内容的提问来源于stack exchange,提问作者ihatec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:35:41