检查文件每一行的某些属性

检查文件每一行的某些属性

我有几个(准确地说是 427 个)文本文件,每行包含 100 万行,其中包含 31 个以空格(可能是双空格)分隔的数字。然而,可能存在一些数据损坏,并且可能存在包含垃圾的行。

我现在想检查每行是否满足包含 31 个由空格分隔的项目的属性(我假设这些项目是数字。也能检查这一点的方法会更好)。

我目前的方式是

while read line;
do
   if [ $(echo "$line" | sed 's/ /\n/g' | grep -v "^$" | wc -l) -ne 31 ]
   then
      echo "$file bad";
   fi
done < $file

这会用换行符替换一行中的所有空格,过滤空行,计算行数并将其与 31 进行比较。

这种方法很慢,可能有更好的方法,涉及一些奇特的正则表达式。什么是更快的方法?

答案1

为什么不只是grep一个人呢?

bash-4.2$ cat file
1 2 -3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 -34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 L 51 52 53 54 55 56 57 58 59 60 61 62
63 64 -65 66 67 68 69
70 71 -72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

# listing bad lines in the file
bash-4.2$ grep -Exv '(-?[[:digit:]]+ +){30}-?[[:digit:]]+' file
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 L 51 52 53 54 55 56 57 58 59 60 61 62
63 64 65 66 67 68 69

# listing files with bad lines
bash-4.2$ grep -Exvl '(-?[[:digit:]]+ +){30}-?[[:digit:]]+' -- *
file

答案2

只需执行以下操作:

awk 'NF != 31 || /[^0-9 -]/ {print FILENAME ":" FNR ": " $0}' file1 file2...

报告不包含 31 个字段或包含非数字的行。不像@manatwork的解决方案那么严格,因为它不会咆哮---9-8例如,但它可能更有效。

答案3

您可以使用 将该行读入数组read -a,然后检查数组的大小。这应该比生成一个子 shell 来每行分叉 3 个进程要好得多。

while read -ra line;
do
    if (( ${#line[@]} != 31 )); then
        echo "$file bad"
    fi
done < "$file"

相关内容