查找仅在文件中显示一行的行

问题描述 投票:1回答:2

假设我有100行的文件。在文件中有很多行重复自己,只有一行不重复。

我想找到只显示一次的行。是否有一个命令或我是否必须构建一个复杂的循环如下?

我的代码到目前为止:

#!/bin/bash
filename="repeat_lines.txt"

var="$(wc -l <$filename )"
echo "length:" $var
#cp ex4.txt ex4_copy.txt
for((index=0; index < var; index++));
do
    one="$(head -n $index $filename | tail -1)"
    counter=0
        for((index2=0; index2 < var; index2++));
        do
            two="$(head -n $index2 $filename | tail -1)"
            if [ "$one" == "$two" ]; then
                counter=$((counter+1))
            fi
        done
    echo $one"is "$counter" times in the text: "
done
linux bash file
2个回答
4
投票

如果我理解你的问题,那么

sort repeat_lines.txt | uniq -u应该做的伎俩。

例如对于包含以下内容

a
b
a
c
b

它将输出c

有关进一步参考,请参阅sort manpageuniq manpage


1
投票

你有一个合理的答案,使用标准的shell工具sortuniq。这可能是您想要使用的解决方案,如果您想要便携式且不需要bash的东西。

但另一种方法是使用内置于bash shell中的功能。一种方法可能是使用关联数组,这是bash 4及更高版本的一个特性。

$ cat file.txt
a
b
c
a
b
$ declare -A lines
$ while read -r x; do ((lines[$x]++)); done < file.txt
$ for x in "${!lines[@]}"; do [[ ${lines["$x"]} -gt 1 ]] && unset lines["$x"]; done
$ declare -p lines
declare -A lines='([c]="1" )'

我们在这里做的是:

  1. declare -A创建关联数组。这是我提到的bash 4功能。
  2. while循环读取文件的每一行,并递增一个计数器,该计数器使用文件行的内容作为关联数组中的键。
  3. for循环遍历数组,删除计数器大于1的任何元素。
  4. declare -p以可预测,可重复使用的格式打印数组的详细信息。您可以交替使用另一个for循环来逐步执行其余的数组元素(其中可能只有一个)以便对它们执行某些操作。

请注意,此解决方案虽然适用于小文件(例如,最多几千行),但对于非常大的文件(例如数百万行)可能无法很好地扩展。 Bash不是以这种方式读取输入最快的,并且在使用数组时必须认识到内存限制。

sort替代方案具有内存优化的优势,使用磁盘上的文件来处理超大文件,但代价是速度。

如果您只处理几百行的文件,那么很难预测哪种解决方案会更快。最后,输出形式可能决定了您选择的解决方案。 sort | uniq管道生成标准输出列表。上面的bash解决方案生成与数组中的键相同的列表。否则,它们在功能上是等同的。

© www.soinside.com 2019 - 2024. All rights reserved.