我有几个(准确地说是 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"