BASH-判断是否存在重复行(y/n)



我正在编写一个操作文本文件的脚本。

我想做的第一件事是检查是否存在重复条目,如果存在,请询问用户我们是要保留还是删除它们。

如果存在重复行,我知道如何显示,但我想学习的只是得到"是否存在重复行?"问题的是/否答案

似乎uniq将返回0,无论是在发现重复的情况下,还是在命令没有问题的情况下完成。

我可以在if-语句中输入什么命令来告诉我是否存在重复行?

我的文件非常简单,它只是单列中的值。

我可能会使用awk来完成这项工作,但为了多样化,这里有一个简单的管道来完成同样的事情:

$ { sort | uniq -d | grep . -qc; } < noduplicates.txt; echo $?
1
$ { sort | uniq -d | grep . -qc; } < duplicates.txt; echo $?
0

sort+uniq -d确保只有重复的行(不必相邻(被打印到stdoutgrep . -c计算那些模仿wc -l的行,有用的副作用是,如果不匹配(即零计数(,它会返回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

您可以将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

然而,[]与其他编程语言一样,是而不是,只是括号[testbash内置命令的同义词,]是它的最后一个参数。您需要阅读help [才能理解

一个快速的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来删除重复项。CCD_ 27评估为关键字CCD_ 29的关联数组CCD_。[ "$duplicates" = yes ]是用于测试的bash内置语法。如果测试成功,则评估&&之后的任何情况。

但请注意,awk解决方案可能会更快,因此如果您希望处理更大的文件,则可能需要使用它们。

您可以使用以下awk一行代码执行uniq=yes/no

awk '!seen[$0]{seen[$0]++; i++} END{print (NR>i)?"no":"yes"}' file
  • awk使用一个名为seen的unique数组
  • 每次我们将一个元素放入unique中时,我们都会增加一个计数器i++
  • 最后,在END块中,我们将记录数与此代码中唯一的记录数进行比较:(NR>i)?
  • 如果条件为true,则表示存在重复的记录,并且我们打印no,否则它将打印yes

相关内容

  • 没有找到相关文章

最新更新