我正在编写一个脚本来操作文本文件。
我要做的第一件事是检查是否存在重复的条目,如果存在,请询问用户是否要保留或删除它们。
我知道如果它们存在,如何显示重复的行,但我想要学习的只是得到“是否存在重复项?”这个问题的是/否答案。
如果找到重复项,只要命令完成没有问题,uniq
似乎会返回0
。
我可以在if
语句中添加什么命令,只是为了告诉我是否存在重复的行?
我的文件非常简单,只是单列中的值。
答案 0 :(得分:5)
我可能会使用awk
来做这件事但是,为了多样化,这里有一个简短的管道来完成同样的事情:
$ { sort | uniq -d | grep . -qc; } < noduplicates.txt; echo $?
1
$ { sort | uniq -d | grep . -qc; } < duplicates.txt; echo $?
0
sort
+ uniq -d
确保只有重复的行(不必相邻)打印到stdout
,grep . -c
计算这些行wc -l
1}}带有有用的副作用,如果它不匹配(即零计数),它返回1
而-q
只是静音输出,所以它不会打印行数,所以你可以在脚本中静默使用它。
has_duplicates()
{
{
sort | uniq -d | grep . -qc
} < "$1"
}
if has_duplicates myfile.txt; then
echo "myfile.txt has duplicate lines"
else
echo "myfile.txt has no duplicate lines"
fi
答案 1 :(得分:3)
您可以将awk
与布尔||
运算符结合使用:
# Ask question if awk found a duplicate
awk 'a[$0]++{exit 1}' test.txt || (
echo -n "remove duplicates? [y/n] "
read answer
# Remove duplicates if answer was "y" . I'm using `[` the shorthand
# of the test command. Check `help [`
[ "$answer" == "y" ] && uniq test.txt > test.uniq.txt
)
||
之后的块只有在awk命令返回1时才会被执行,这意味着它找到了重复项。
但是,为了基本了解,我还会展示一个使用if
块的示例
awk 'a[$0]++{exit 1}' test.txt
# $? contains the return value of the last command
if [ $? != 0 ] ; then
echo -n "remove duplicates? [y/n] "
read answer
# check answer
if [ "$answer" == "y" ] ; then
uniq test.txt > test.uniq.txt
fi
fi
然而[]
不只是括号,就像在其他编程语言中一样。 [
是test
bash内置命令和]
最后一个参数的同义词。您需要阅读help [
才能理解
答案 2 :(得分:1)
你可以使用这个awk one-liner执行uniq=yes/no
:
awk '!seen[$0]{seen[$0]++; i++} END{print (NR>i)?"no":"yes"}' file
seen
的唯一数组。i++
。END
块中,我们将此记录中的记录数与此代码中的唯一记录数进行比较:(NR>i)?
no
否则会打印yes
。答案 3 :(得分:1)
快速bash解决方案:
#!/bin/bash
INPUT_FILE=words
declare -A a
while read line ; do
[ "${a[$line]}" = 'nonempty' ] && duplicates=yes && break
a[$line]=nonempty
done < $INPUT_FILE
[ "$duplicates" = yes ] && echo -n "Keep duplicates? [Y/n]" && read keepDuplicates
removeDuplicates() {
sort -u $INPUT_FILE > $INPUT_FILE.tmp
mv $INPUT_FILE.tmp $INPUT_FILE
}
[ "$keepDuplicates" != "Y" ] && removeDuplicates
脚本从INPUT_FILE逐行读取,并将关联数组a
中的每一行存储为键,并将字符串nonempty
设置为值。在存储值之前,它首先检查它是否已经存在 - 如果它存在意味着它找到了重复项并且它设置了duplicates
标志然后它就会突破循环。
稍后它只检查是否设置了标志并询问用户是否保留重复项。如果他们回答Y
以外的任何内容,则会调用removeDuplicates
函数,该函数使用sort -u
删除重复项。 ${a[$line]}
计算关键字a
的关联数组$line
的值。 [ "$duplicates" = yes ]
是用于测试的bash内置语法。如果测试成功,则评估&&
之后的任何内容。
但请注意,awk解决方案可能会更快,因此如果您希望处理更大的文件,可能需要使用它们。