Linux ボックス上に大量のログ ファイルがあり、第三者に送信する前に機密データを消去する必要があります。以前、このタスクを実行するために以下のスクリプトを使用しましたが、うまくいきました (スクリプトはここからの助けを借りて作成されました :-) ):
#!/bin/bash
help_text () {
cat <<EOF
Usage: $0 [log_directory] [client_name(s)]
EOF
exit 0
}
CMDLINE=""$0" "$@""
if [ -z "$1" ]; then
help_text
else
pattern=""
delim=""
n=1
counter=`find "$1" -name *.gz |sort |wc -l`
BAKIFS=$IFS
IFS=$(echo -en "\n\b")
exec 3<&0
exec 0<"$2"
while read -r line
do
pattern=$pattern$delim$line
delim="|"
done
exec 0<&3
IFS=$BAKIFS
while [ $n -lt $counter ]
do
for i in `find "$1" -name *.gz |sort`
do
gunzip "$i"
i_unzip=$(echo "$i" |sed 's/\.[^\.]*$//')
sed -ri "s/$pattern/CLIENT/g" "$i_unzip"
gzip "$i_unzip"
done
n=n+1
done
fi
exit 0
しかし、今、私たちの部署の1つからCLIENT_FILE.txtが送られてきました。425000+変数です!内部制限に達した可能性があります。これほど多くの変数を処理する方法についてアイデアをお持ちの方がいらっしゃいましたら、ぜひ教えてください。
クライアント ファイルを 4 つに分割して、それぞれに約 100,000 個の変数を持たせようとしましたが、それでもうまくいきません。ただし、20 個のディレクトリがあり、各ディレクトリに最大 190 個のファイルがあるため、これ以上分割するのは気が進みません。作成するクライアント ファイルが増えるほど、実行しなければならないパスの数も増えます。
答え1
私は次のようなことを試してみます:
#!/bin/bash
files=()
while read file; do
gunzip "$file" && files+=( "${file%.gz}" )
done < <(find "$1" -name '*.gz')
awk '
FILENAME == ARGV[1] {
client_name[$0]++
next
}
FNR == 1 {
output = FILENAME ".new"
}
{
for (i=1; i<=NF; i++) {
if ($i in client_name)
$i = "CLIENT"
}
print > output
}
' "$2" "${files[@]}"
for file in "${files[@]}"; do
mv "$file" "$file.old" &&
mv "$file.new" "$file" &&
gzip "$file"
done
ログ ファイルに単純なスペース区切りの行以外のものが含まれている場合、awk スクリプトによってフォーマットが乱れる可能性があります。
答え2
sed
パターンをファイルに書き込んで、sed
オプションを使用してに渡すようにしてください--file=
。コマンドラインパラメータは、大量のデータを渡すためのものではありません。