bash:ログを解析可能な塊に分割する

bash:ログを解析可能な塊に分割する

logsvn履歴を含む変数があります。

$ log=$(svn log -r 9:11)
$ echo "%s\n" "$log"
------------------------------------------------------------------------
r9 | stew | 2021-03-06 20:14:57 +0100 (Sat, 06 Mar 2021) | 1 line

Moving things to trunk
------------------------------------------------------------------------
r10 | stew | 2021-03-06 20:16:27 +0100 (Sat, 06 Mar 2021) | 1 line

Adding script svn2redmine
------------------------------------------------------------------------
r11 | stew | 2021-03-06 20:19:38 +0100 (Sat, 06 Mar 2021) | 2 lines

Moving stuff to a file execute permissions.
This is a multi-line message
------------------------------------------------------------------------

個々のコミットメッセージを解析する素晴らしいスクリプトがあります。しかし今はこう呼びます。

for rev in {9..11}; do
  parse "$(svn log -r $rev)"
done

つまり、要求がたくさんあり、svn log各要求がサーバーに別の接続を確立するため、遅くなります。私はむしろ:

log=$(svn log -r 9:11)
for commit in "$log"; do
  parse "$commit"
done

しかし、どのように別々のコミットに分けることができますか"$log"

答え1

"$log"提出物を含む配列に変換する必要があります。分割は複数文字の文字列に基づいて行う必要があるため、IFS=ここでは役に立ちません。

log=$(svn log -r 9:11)

... Something here to split "$log" into an array of commits ...

for commit in "${commits[@]}"; do
  parse "$commit"
done

この分割は以下に基づいています。この回答次のようになります。

delimiter='------------------------------------------------------------------------'
export -a commits
while [ "$log" != "${log#*$delimiter}" ]; do
   part="${log%%$delimiter*}"
   part="${part##$'\n'}"
   commits+=("${part%%$'\n'}")
   log="${log#*$delimiter}"
done

どこ:

  • "${log#*$delimiter}"最初の区切り文字の前にあるすべての項目を削除します(含む)。
  • "${log%%$delimiter*}"次の区切り文字まで(含まれていない)すべての項目を抽出します。
  • "${part##$'\n'}"\n区切り文字の末尾から先行削除
  • "${part%%$'\n'}"\nメッセージの末尾から末尾を削除する

関連情報