Quantcast
Viewing all articles
Browse latest Browse all 2722

[Bash] 3つ以上のファイルから共通行を求めるシェルスクリプト

はじめに

最近仕事で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

OptionDescription
--version, -vprint intersect.sh version
--help, -hprint help

おわりに

今回はこのようなロジックにしたが、1つのファイルのなかで、値が重複しなければuniq -cのカウントの値がファイル数と一致するはずなので、

$cat file1 file2 file3 file4 | sort | uniq-c | sedで置換 | cutで切り取り

みたいな形でもできそう。


Viewing all articles
Browse latest Browse all 2722

Trending Articles