用于读取文件、排序和打印重复记录及其标识号的 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