PerlでChangeLogの株分け

grep-changelogのソースを理解する前に、ChangeLogのフォーマットの理解を兼ねて、Logを小分けするスクリプトを作ってみます。
タイトルの、Logを株分けってのは、私が作った言葉です。複数のChangeLogを一つずつ小分けして、Hashに突っ込むことを、どのようにタイトルにするか悩んだ末、ChangeLogを成長した作物に見立てて株分けとしました。一応英語もdivisionなので意味は合ってます。
いきなり完成版を作るのは、難しいので、少しずつ作ります。

まずは、ChangeLogという名称を含むファイル一覧を作るスクリプト。
opendirで全ファイル一覧を取得して、grepでフィルタリングしてます。

takk@deb9:~/src/binutils-2.28/binutils$ cat t.pl
opendir(DIR,".");
@files = grep { /ChangeLog/ } readdir(DIR);
closedir(DIR);

foreach(@files){
	print "$_\n";
}
takk@deb9:~/src/binutils-2.28/binutils$ 

使ってみます。

takk@deb9:~/src/binutils-2.28/binutils$ perl t.pl
ChangeLog-2009
ChangeLog-2006
ChangeLog-2014
ChangeLog-2015
ChangeLog-9899
ChangeLog-2012
ChangeLog-2011
ChangeLog-0001
ChangeLog-0203
ChangeLog-2005
ChangeLog
ChangeLog-2008
ChangeLog-9197
ChangeLog-2007
ChangeLog-2004
ChangeLog-2013
ChangeLog-2016
ChangeLog-2010
takk@deb9:~/src/binutils-2.28/binutils$ 

次は、抽出したファイルを一つずつオープンし、行頭に年-月-日の文字列がある行をIDとして、抽出します。

opendir(DIR,".");
@files = grep { /ChangeLog/ } readdir(DIR);
closedir(DIR);

foreach(@files){
	open(INFILE,"<$_");
	$id = "";
	while(<INFILE>){
		chomp();
		if(/^\d\d\d\d-\d\d-\d\d/){
			$id = "$_";
			print "$id\n";	
		}
	}
	close(INFILE);
}

これを実行すると、このように各ログが出力されます。

takk@deb9:~/src/binutils-2.28/binutils$ perl t.pl | shuf | head
2010-04-27  Nick Clifton  <nickc@redhat.com>
2002-07-10  Jakub Jelinek  <jakub@redhat.com>
2012-05-11  Daniel Richard G.  <skunk@iskunk.org>
2016-05-18  Maciej W. Rozycki  <macro@imgtec.com>
2001-08-03  John Healy  <jhealy@redhat.com>
2004-01-02  Nick Clifton  <nickc@redhat.com>
2000-04-05  Alan Modra  <alan@linuxcare.com.au>
2016-08-12  Nick Clifton  <nickc@redhat.com>
2009-03-02  Cary Coutant  <ccoutant@google.com>
2012-05-02  Nick Clifton  <nickc@redhat.com>
takk@deb9:~/src/binutils-2.28/binutils$ 

次に、抽出したIDをHashのキーとして、各ログ本体をHashに格納します。このとき、元々のフォーマットである行頭にTABがある行をログ本体とみなし、TABを含めて文字列を一行の文字列に連結します。Hashからログを取り出すときは、TABを使用してsplitします。

foreach(@files){
	open(INFILE,"<$_");
	$id = "";
	while(<INFILE>){
		chomp();
		if(/^\d\d\d\d-\d\d-\d\d/){
			$id = "$_";
			next;
		}
		if(/^	|^$/ && $id ne ""){
			$log{$id} .= "$_";
			next;
		}
		last;
	}
	close(INFILE);
}

Hashから取り出して表示する処理です。

foreach(keys %log){
	$id = $_;
	@tmp = split /\t/,$log{$_};

	print "$id\n";
	foreach(@tmp){
		print"	$_\n";
	}	
	print"\n";
}

全文です。

takk@deb9:~/src/binutils-2.28/binutils$ cat -n t.pl
     1	%log=();
     2	opendir(DIR,".");
     3	@files = grep { /ChangeLog/ } readdir(DIR);
     4	closedir(DIR);
     5	
     6	foreach(@files){
     7		open(INFILE,"<$_");
     8		$id = "";
     9		while(<INFILE>){
    10			chomp();
    11			if(/^\d\d\d\d-\d\d-\d\d/){
    12				$id = "$_";
    13				next;
    14			}
    15			if(/^	|^$/ && $id ne ""){
    16				$log{$id} .= "$_";
    17				next;
    18			}
    19			last;
    20		}
    21	
    22		close(INFILE);
    23	}
    24	
    25	foreach(keys %log){
    26		$id = $_;
    27		@tmp = split /\t/,$log{$_};
    28	
    29		print "$id\n";
    30		foreach(@tmp){
    31			print"	$_\n";
    32		}	
    33		print"\n";
    34	}
takk@deb9:~/src/binutils-2.28/binutils$ 

実行すると、このように抽出されます。

takk@deb9:~/src/binutils-2.28/binutils$ perl t.pl | head -20
2008-10-31  Alan Modra  <amodra@bigpond.net.au>
	
	* po/id.po: New file.
	* configure.in (ALL_LINGUAS): Add id.
	* configure: Regenerate.

2005-10-04  Nick Clifton  <nickc@redhat.com>
	
	* cxxfilt.c: Treat mangled names specified on the command line in
	the same way as mangled names read from stdin.
	Add -i switch to disable the display of implementation details.
	Add -t switch to disable the demangling of types.
	* NEWS: Mention the new switches.
	* doc/binutils.texi (cxxfilt): Document the -i and -t switches.

2004-10-08  Daniel Jacobowitz  <dan@debian.org>
	
	* readelf.c (get_x86_64_section_type_name): New function.
	(get_section_type_name): Use it.

takk@deb9:~/src/binutils-2.28/binutils$ 

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA