はじめに
最近仕事で1週間ずっと処理に失敗しているものをlogから抽出するという調査があった。
Linuxのcommコマンドを利用すれば2日分のlogファイルの共通行を求めることが出来たのだが、Linuxのcommコマンドでは3つ以上のファイルの共通行を求めることは出来なさそうだった。
(commコマンドをパイプでつなぎまくればできるんやけど。。。)
共通行の求め方は色々あるとは思うが、bashでintersect.shというシェルスクリプトを作ってみた。
これはその時の記録。
intersect.sh
複数のファイルから共通の行を取得するためのシェルスクリプト。
このシェルスクリプトは、3つ以上のファイルから共通の行を取得することをサポートしている。
Code
intersect.sh
#!/usr/bin/env bashset-u######################################## Define usage# Globals:# ${0}# Arguments:# None# Returns:# None#######################################function usage {cat<<EOF$(basename${0}) is a tool to get common lines from multiple files.
Usage:
sh $(basename${0}) file1 file2 file3 file4 ...
sh $(basename${0}) file?
sh $(basename${0}) file*
Options:
--version, -v print ${0} version
--help, -h print this
EOF
exit 0
}######################################## Define version# Globals:# ${0}# Arguments:# None# Returns:# None#######################################function version {echo"$(basename${0}) version 0.0.2 "exit 0
}######################################## Print message with color# Globals:# None# Arguments:# color# Returns:# None#######################################function cecho {local color=$1shift
echo-e"\033[${color}m$@\033[m"}# If there is no argument then print usage.if[$# -eq 0 ];then
usage
fi# Check 1st argumentcase${1}in--help|-h)
usage
;;--version|-v)
version
;;esac# Define readonly values for color codedeclare-rGREEN=32
declare-rRED=31
declare-rYELLOW=33
declare-rBLUE=34
declare-iis_error=0
declare-afile_path_list=()# Get target file path from command argumentsfor argument in"${@}"do
if[-r"${argument}"];then
file_path_list+=("${argument}")else
cecho ${RED}$(printf"Cannot read file (%s).""${argument}")is_error=1
fi
done
if[${is_error}-eq 1 ];then
exit 1
fi
IFS=$'\n'declare-aintersect_value_list=()declare-aline_list=($(cat"${file_path_list[0]}" | sort | uniq))# Get intersect values by grep each filefor line in"${line_list[@]}"do
is_error=0
for file_path in"${file_path_list[@]}";do
result=$(grep-E"^${line}$""${file_path}")if[!$?-eq 0 ];then
is_error=1
break
fi
done
if[${is_error}-eq 0 ];then
intersect_value_list+=("${line}")fi
done# print intersect valuesfor intersect_value in"${intersect_value_list[@]}";do
echo-e"${intersect_value}"done
exit 0
https://github.com/mizutsu/intersect.sh
Shell type
Bash
Usage
引数にファイルを1つ1つ設定する
$sh intersect.sh file1.log file2.log file3.log file4.log ...
例
$cat file1.log
This is sample A.
This is sample B.
This is sample C.
This is sample D.
$cat file2.log
This is sample A.
This is sample B.
$cat file3.log
This is sample A.
This is sample C.
$cat file4.log
This is sample A.
This is sample D.
$sh intersect.sh file1.log file2.log file3.log file4.log
This is sample A.
ワイルドカードを使うことも可能。
sh intersect.sh file?.log
sh intersect.sh file*
例
$cat file1.log
This is sample A.
This is sample B.
This is sample C.
This is sample D.
$cat file2.log
This is sample A.
This is sample B.
$cat file3.log
This is sample A.
This is sample C.
$cat file4.log
This is sample A.
This is sample D.
$sh intersect.sh file?.log
This is sample A.
$sh intersect.sh file*This is sample A.
Options
Option | Description |
---|---|
--version, -v | print intersect.sh version |
--help, -h | print help |
おわりに
今回はこのようなロジックにしたが、1つのファイルのなかで、値が重複しなければuniq -c
のカウントの値がファイル数と一致するはずなので、
$cat file1 file2 file3 file4 | sort | uniq-c | sedで置換 | cutで切り取り
みたいな形でもできそう。