掃除
スクリプトに機能を追加する前に、既存のスクリプトをクリーンアップする必要があります。
I/O リダイレクション — 繰り返さないでください
このような壁から壁への I/O のリダイレクトを見ると、泣きたくなるのです。それをすべて回避するには、次の 3 つのオプションがあります。
for file in $(find . -name "*.csv" )
do
echo "===================================================="
echo "$file"
echo "----------------------------------------------------"
echo "Contacts BEFORE purge:"
wc -l $file | cut -d " " -f1
echo " "
cat $file | egrep -v "xxx|yyy|zzz" | grep -v -E -i '([0-z])\1{2,}' | uniq | sort -u > tmp_file
mv tmp_file $file ;
echo "Contacts AFTER purge:"
wc -l $file | cut -d " " -f1
done >> db_purge_log.txt
または:
{
for file in $(find . -name "*.csv" )
do
echo "===================================================="
echo "$file"
echo "----------------------------------------------------"
echo "Contacts BEFORE purge:"
wc -l $file | cut -d " " -f1
echo " "
cat $file | egrep -v "xxx|yyy|zzz" | grep -v -E -i '([0-z])\1{2,}' | uniq | sort -u > tmp_file
mv tmp_file $file ;
echo "Contacts AFTER purge:"
wc -l $file | cut -d " " -f1
done
} >> db_purge_log.txt
あるいは:
exec >>db_purge_log.txt # By default, standard output will go to db_purge_log.txt
for file in $(find . -name "*.csv" )
do
echo "===================================================="
echo "$file"
echo "----------------------------------------------------"
echo "Contacts BEFORE purge:"
wc -l $file | cut -d " " -f1
echo " "
cat $file | egrep -v "xxx|yyy|zzz" | grep -v -E -i '([0-z])\1{2,}' | uniq | sort -u > tmp_file
mv tmp_file $file ;
echo "Contacts AFTER purge:"
wc -l $file | cut -d " " -f1
done
最初の形式は、I/O リダイレクトを提供する単一のループを持つこのスクリプトに適しています。2 番目の形式では、{
andを使用して、}
より一般的なコマンド シーケンスを処理します。を使用する 3 番目の形式exec
は「永続的」です。元の標準出力を復元することはできませんが、{
...}
フォームを使用すると、スクリプトのさまざまなセクションをさまざまな場所に書き込むことができます。
これらすべてのバリエーションのもう1つの利点は、必要に応じて、標準出力を送信しているのと同じ場所にエラーを簡単に送信できることです。例えば:
exec >>db_purge_log.txt 2>&1
その他の問題
wc
次の代わりに —からファイル名を抑制:
wc -l $file | cut -d " " -f1
使用する:
wc -l < $file
UUOCcat
— 以下の代わりに— を無用に使用:
cat $file | egrep -v "xxx|yyy|zzz" | grep -v -E -i '([0-z])\1{2,}' | uniq | sort -u > tmp_file
使用する:
egrep -v "xxx|yyy|zzz" $file | grep -v -E -i '([0-z])\1{2,}' | uniq | sort -u > tmp_file
UUOU — の無駄な使用uniq
uniq
なぜandが必要なのかはまったく明らかではありませんsort -u
。でsort -u
十分なので、次のようになります。
egrep -v "xxx|yyy|zzz" $file | grep -v -E -i '([0-z])\1{2,}' | sort -u > tmp_file
UUOG — の無駄な使用grep
egrep
は同等でgrep -E
あり、両方とも複数の正規表現を処理できます。2 番目の式は、括弧内の式が 3 回以上一致するものと一致します (実際には 3 回一致するだけで済みます)。したがって、実際には 2 番目の式が一致します。最初の仕事。そして[0-z]
試合は怪しい。おそらく、大文字と小文字の数字だけでなく-i
、さまざまな句読点にも一致しますが、 .
grep -Eiv '([0-9a-z]){3}' $file | sort -u > tmp_file
スペースを含むファイル名
このコードは、for file in $(find ...)
表記のため、スペース、タブ、または改行を含むファイル名を処理しません。おそらく、今それを扱う必要はありません — 問題に注意してください。
最後のクリーンアップ
for file in $(find . -name "*.csv" )
do
echo "===================================================="
echo "$file"
echo "----------------------------------------------------"
echo "Contacts BEFORE purge:"
wc -l < $file
echo " "
grep -Evi '([0-9a-z]){3}' | sort -u > tmp_file
mv tmp_file $file
echo "Contacts AFTER purge:"
wc -l <$file
done >> db_purge_log.txt
余分な機能を追加する
このループの途中のどこかに、別のファイルを抑制リストとして使用するコマンドを追加したいと思います。.csv
つまり、その抑制リストで完全一致として見つかったすべての行を から削除する必要があります$file
。
既に入力ファイル ( $file
) を並べ替えているので、抑制ファイルを並べ替えることができます (suppfile='suppressions.txt'
まだ並べ替えられていない場合は、それも呼び出します。そのため、 を使用して、 とcomm
の両方に表示される行を削除し$file
ます$suppfile
。 (または、この場合のように、ファイルの編集およびソートされたバージョンにのみ表示される行$file
)、したがって、共通のエントリを抑制し、そこからのエントリ$suppfile
は表示されません$file
。comm -23 - "$suppfile"
、標準入力からファイルをソート-
し、からのエントリを除外します"$suppfile"
suppfile='suppressions.txt' # Must be in sorted order
for file in $(find . -name "*.csv" )
do
echo "===================================================="
echo "$file"
echo "----------------------------------------------------"
echo "Contacts BEFORE purge:"
wc -l < "$file"
echo " "
grep -Evi '([0-9a-z]){3}' | sort -u | comm -23 - "$suppfile" > tmp_file
mv tmp_file "$file"
echo "Contacts AFTER purge:"
wc -l < "$file"
done >> db_purge_log.txt
抑制ファイルがソートされていない場合は、単純に一時ファイルにソートします。.csv
現在のディレクトリの抑制ファイルに接尾辞を使用することに注意してください。抑制ファイルのすべての行が抑制ファイルの行と一致するため、ファイルをキャッチして空にします。これは、抑制ファイルの後に処理されるファイルには役立ちません。
おっと —grep
正規表現を単純化しすぎました。(おそらく)次のようになります。
grep -Evi '([0-9a-z])\1{2}' $file
その違いはかなりのものです。123
私の元の書き直しでは、隣接する 3 つの数字または文字 (たとえば、 またはabz
)を探します。リビジョン (実際には元のコマンドの 1 つと非常によく似ています) は[0-9A-Za-z]
、同じ文字が 2 回出現する (たとえば111
orで、 oraaa
ではありません) からの文字を探します。123
abz
代替案xxx|yyy|zzz
が実際に 3 文字の繰り返しではない可能性がある場合は、 を 2 回連続して呼び出す必要があるかもしれませんgrep
。