ファイルの各行の特定の属性を確認してください。

ファイルの各行の特定の属性を確認してください。

私はそれぞれ、スペース(おそらく二重スペース)で区切られた31の数字を含む100万行を含む複数の(正確に427の)テキストファイルを持っています。ただし、一部のデータ破損がある可能性があり、ガベージを含む行がある可能性があります。

次に、各行がスペースで区切られた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

これは、1行のすべてのスペースを改行文字に置き換え、空白行をフィルタリングし、行数を計算して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配列のサイズを確認するために使用できます。これは、1行に3つのプロセスを分岐するサブシェルを作成するよりもはるかに優れています。

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

関連情報