用于读取文件、排序和打印重复记录及其标识号的 Bash 脚本

Posted

技术标签:

【中文标题】用于读取文件、排序和打印重复记录及其标识号的 Bash 脚本【英文标题】:Bash Script to Read File, Sort and Print Duplicate Records, and their Identity Number 【发布时间】:2021-12-12 10:18:55 【问题描述】:

我有一个包含数千条记录的文件,这些记录根据它们共同的身份号码的前 6 位分组为子组,但有些记录是重复的。 我正在尝试创建一个 bash 脚本来读取文件,查找重复记录和它们共享的标识号,并打印出它们下的标识号和重复记录。

当前脚本:

#!/bin/bash
########## script to find duplicate records & their ID
INPUT="sourceFile.txt"
while read varName; do
  echo "$varName"
  if [ "$varName" = "NEXT" ]; then
    sort $INPUT | uniq -d
    echo "END OF ONE ID-NUMBER IN FILE"
  fi
done < "$INPUT"

示例 INPUT_FILE:

NEXT
123456-
# requesting: displayName
displayName: Alpha Beta
displayName: Charly Delta Echo
displayName: Xerox Yingyang Zenox
displayName: Xerox Yingyang Zenox

NEXT
123999-
# requesting: displayName
displayName: Golf Harvey Indigo
displayName: Jaguar Kingston Lambda
displayName: Alma Nano Matter
displayName: Oxygen Pascal Queen
displayName: Romeo Saint Tropez Unicorn
displayName: Vauxhall Wellignton Woolwhich
displayName: Rodrigo Compton Hilside
displayName: Vauxhall Wellignton Woolwhich
NEXT

期望输出/预期输出:

NEXT
123456-
displayName: Xerox Yingyang Zenox
displayName: Xerox Yingyang Zenox

END OF ONE ID-NUMBER IN FILE

NEXT
123999-
displayName: Vauxhall Wellignton Woolwhich
displayName: Vauxhall Wellignton Woolwhich

感谢您提供预期的想法和线索。

【问题讨论】:

你能提供你想要的输出吗?请编辑您的帖子,而不是在评论中。 在循环的每次迭代中,您都在对完整的sourceFile.txt 进行排序。这根本不符合逻辑。您必须在标准输出上获得相同的排序文件,其中有 NEXT 的次数。您应该只对 NEXT 和下一个之间的那部分进行排序。 @Asquared - 除了最后一个输出组之后,您真的想要END OF ONE ID-NUMBER IN FILE 行吗?对于没有重复的组,您想要什么输出? 【参考方案1】:

我不知道为什么你想要重复的行两次,我不明白输出中间的“END OF ONE ID-NUMBER IN FILE”行在做什么。

以下仅显示重复项。

#! /bin/bash

read -r next; unset next
while true; do
  read -r id || break
  read -r comment; unset comment
  dns=()
  while read -r dn; do
    if [[ $dn =~ ^NEXT$ ]]; then
      printf 'NEXT\n'
      printf '%s\n' "$id"
      printf '%s\n' "$dns[@]" | sort | uniq -d
      break
    else
      dns+=("$dn")
    fi
  done
done

如果你真的想硬编码输入文件的名称,你可以在开头添加以下行:

exec < sourceFile.txt

【讨论】:

【参考方案2】:

sort 显然对整个文件进行了排序。我会将其重构为一个简单的 Awk 脚本。


awk '/^NEXT/  delete a;
      if(NR>1)  print ""; print "END OF ONE ID-NUMBER IN FILE"; print ""; 
      id=""; print; next 
    id == ""  id = $0; print; next 
    !/^displayName:/  next 
    $0 in a  print; if (a[$0] == 1) print; 
     a[$0]++ ' sourceFile.txt

一旦您熟悉了 Awk 的基础知识,这应该相当简单。但简而言之,我们保留一个关联数组a,在其中我们记住我们已经看到了哪些displayName: 行,当我们看到重复时,我们打印(如果它还没有打印的话,原始的,和)最新出现的.

其中一些有点难看,因为您的要求相当没有吸引力;也许更好的设计是在同一行仅打印具有相关 ID 号的实际副本。

awk '/^NEXT/  delete a; id=""; next 
    id == ""  id = $0; next 
    !/^displayName:/  next 
    $0 in a  if(a[$0] == 1) print id ":" $0 
     a[$0]++ ' sourceFile.txt

重复的东西已经足够了,所以我们只打印记录中第二次出现的东西。

【讨论】:

以上是关于用于读取文件、排序和打印重复记录及其标识号的 Bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章

删除重复的数组条目

我无法按字母顺序对文件中的“姓氏”进行排序:我得到中止陷阱:6

TXT 文件上的 Python 项目,如何读取字数和排序

当我指定要打印的字段时,为啥 AWK 在文件操作的默认读取记录中打印整行

asp中如何读取当前记录的上一条和下一条记录

6