正規表現とgrep / perlを使用したpom.xmlのgitログのフィルタリング

正規表現とgrep / perlを使用したpom.xmlのgitログのフィルタリング

pom.xml正規表現を使用してファイルログの内容をフィルタリングしたいと思います。

私が作成した日付正規表現PCREを使用して動作します。私の正規表現は次のとおりです。

commit \K[a-z0-9]*(?=[\s\S]*\+.*<version>1.2.0)

それから私は次を実行してみました。

git log --full-history -p pom.xml | grep -P "commit \K[a-z0-9]*(?=[\s\S]*\+.*<version>1.2.0)"

そして

git log --full-history -p pom.xml | perl -nle 'print \$1 if /commit \K[a-z0-9]*(?=[\s\S]*\+.*<version>1.2.0)/'

しかし、それらのどれも動作しません(何も一致しないようです)。

確かに何か抜けたものがあるのに何なのかわかりません。

編集する:

これを明確にするために、次の例を挙げてみましょうgit log

commit a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f
Author: Author <[email protected]>
Date:   Wed Mar 30 15:04:29 2022 +0100
 
    commit message
 
diff --git a/pom.xml b/pom.xml
index 93df07e..5f82fd2 100755
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.organization.project</groupId>
        <artifactId>ProjectName</artifactId>
-       <version>1.1.1</version>
+       <version>1.2.0</version>
        <name>ProjectName</name>
        <description>Description of project</description>

version特定の値に変更されたコミットのハッシュを選択したい(1.2.0私が書いた正規表現から)。

明らかに、これは特定のリポジトリで実行されたすべてのコミットのログであり、複数のコミットがある可能性があります。

この入力に上記の正規表現を使用すると、コミットハッシュが出力されます。

a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

これがregexrを使って実際に起こるものです。

ベストアンサー1

ファイルに保存されているサンプルコミットログの場合、gitlogGNUgrepコマンドは次のものを抽出します。

% < gitlog ggrep -Pzo 'commit \K[a-z0-9]*(?=[\s\S]*\+.*<version>1.2.0)'
a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471fmessage%
% < gitlog ggrep -Pzo 'commit \K[a-z0-9]*(?=[\s\S]*\+.*<version>1.2.0)' | od -c
0000000    a   1   3   5   7   f   4   e   1   c   b   2   c   3   4   a
0000020    a   1   a   1   3   5   7   f   4   e   1   c   b   2   c   3
0000040    4   a   a   1   4   7   1   f  \0   m   e   s   s   a   g   e
0000060   \0
0000061

偽の肯定を考慮すると、これは理想的ではないかもしれません。また、PCREフラグのドキュメントには-P実験の実行に関する内容が記載されています-z。行ベースの正規表現を使用すると、一致が^commit開始される位置を制限するために使用できますが、GNUがPerlのように一致位置を変更するフラグを持たない限り、-zこれは発生しません。grep^

% < gitlog perl -0777 -nE 'say $1 if m/^commit (\S+).*<version>1.2.0/ms'
a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

これはGNUフラグ(完全な入力を受け取る)のあまり実験的なバージョン-0777であり、どこでも改行を一致させ、改行をスキップする正規表現フラグです。ただし、正規表現は各コミットに対してログ全体を複数回検索し、必要なバージョン番号を見つけることができないため、これは非常に非効率的になる可能性があります。あるいは、バージョン情報を以前のコミット行の一致に限定することはないので、コミットを複数回一致させることができます。grep -z-0777ms^.

別の方法は、最後のコミットを覚えてバージョン番号を見つけるときにその値を使用することです。これにより、1行ずつ解析できます。

% < gitlog perl -nle 'if (m/^commit (\S+)/) {$commit=$1} if(m/<version>1.2.0/) {print $commit}'
a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

{print $commit;exit}入力の残りの部分(多くの場合があります)に興味がない場合は、一致するバージョンが見つかると検索が停止する可能性があります。

% < gitlog perl -nle 'if (m/^commit (\S+)/) {$commit=$1} if(m/<version>1.2.0/) {print $commit;exit}'
a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

より速い速度のために、次のように書くことができますawk。通常、Perlで書かれた後にしかわかりません。

% < gitlog awk '/^commit/{c=$2};/<version>1.2.0/{print c;exit}'
a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

理想的には、テスト入力(または複数入力)は、ターゲットの前後の複数のコミットレコード、重複レコードなど、さまざまな可能性を実行する必要があります。特に、このコードが無人で何らかの形で使用される場合は、人の介入なしに使用されます。完全性検査結果:

% < gitlog
blah blah blah

commit a1357f4e1cb2c34aa1a1357f4e1cb2c34aa1471f

    commit eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

-       <version>1.1.1</version>
+       <version>1.2.0</version>

commit ffffffffffffffffffffffffffffffffffffffff
+       <version>1.2.0</version>

おすすめ記事