我正在尝试创建一个脚本来读取 git log
的输出并将其放置为一个 XML 文件。
这是脚本的示例。
#!/bin/bash
repo=(/srv/git/repositories)
list1=($repo/test.git)
cd "$list1"
echo '<?xml version="1.0" ?><rss version="2.0"><channel>' >> /tmp/test.xml
for i in $(git log --pretty=format:"%h")
do
for e in $(git log | grep "Author:" | awk '{print $2}')
do
#for f in $(git log --pretty=format:"%cn")
#do
#for g in $(git log --pretty=format:"%cD")
#do
cat << EOF >> /tmp/test.xml
<item><title>$i</title><description></description><author>$e</author><pubDate></pubDate></item>
EOF
#done
#done
done
done
echo '</channel></rss>' >> /tmp/test.xml
当我这样做时,结果是每个提交号和作者将被多次读取和回显。所以我会得到一个像这样的 .xml 文件: 很多相同的提交号!
<rss version="2.0">
<channel>
<item>
<title>906feb6</title>
<description/>
<author>test</author>
<pubDate/>
</item>
<item>
<title>906feb6</title>
<description/>
<author>test</author>
<pubDate/>
</item>
<item>
<title>906feb6</title>
<description/>
<author>test</author>
<pubDate/>
</item>
<item>
<title>**906feb6**</title>
<description/>
<author>test1</author>
<pubDate/>
</item>
<item>
<title>**906feb6**</title>
<description/>
<author>test1</author>
<pubDate/>
<item>
<title>**ffb521e**</title>
<description/>
<author>test1</author>
<pubDate/>
</item>
<channel></rss>
我想要的是每个提交编号都有作者、描述和发布日期。但它必须从这些命令中获取信息。
我想要这样的输出,有人可以帮忙吗?
<item>
<title>906feb6</title>
<description/>test commit 1</description>
<author>test1</author>
<pubDate>Mar, 18<pubDate/>
<item>
<title>**ffb521e**</title>
<description>test commit 2</description>
<author>test2</author>
<pubDate>Mar, 18<pubDate/>
</item>
最佳答案
如@EtanReisner pointed out ,您将循环遍历内部循环中的所有提交,而不仅仅是外部for
循环正在处理的提交。
以下是如何避免 for
循环并解决该问题的方法。
#!/bin/sh
echo '<?xml version="1.0" ?><rss version="2.0"><channel>' > /tmp/test.xml # Make sure we start with an empty file
git log --pretty=format:"%h" |
while read -r i; do
# Presumably you want a single commit here
# See also https://stackoverflow.com/a/4082178/874188
# Also avoid Useless Use of grep
e=$(git log "$i" -1 | awk '/^Author:/{print $2}')
cat <<____EOF >> /tmp/test.xml
<item><title>$i</title><description></description><author>$e</author><pubDate></pubDate></item>
____EOF
done
echo '</channel></rss>' >> /tmp/test.xml
我认为没有理由在开始时将存储库放入两个(原文如此!)数组中。 (如果它只是一个值,为什么要使用数组?)只需在您想要处理的任何存储库中运行它即可。
解决了这个问题,这个脚本中就没有 Bashisms,所以我将 shebang 更改为 #!/bin/sh
。
要将描述等也放入代码片段中,可能是这样的(为了易读而包装;应该只有一行):
git log "$i" -1 --format=format:"<item>%n <title>%h</title>
%n <description>%s</description>%n <author>%an</author>
%n <pubDate>%ad</pubDate>%n</item>"
(2021 年更新)
...但我猜你实际上想要的只是类似的东西
#!/bin/sh
echo '<?xml version="1.0" ?><rss version="2.0"><channel>' > /tmp/test.xml
git log --format=format:"<item>%n <title>%h</title>%n <description>%s</description>%n <author>%an</author>%n <pubDate>%ad</pubDate>%n</item>" >>/tmp/test.xml
# TODO: escape XML specials
echo '</channel></rss>' >> /tmp/test.xml
当您已经拥有(可能格式错误)XML 片段时转义 XML 字符有点棘手,因此可以将 git log --format 替换为更简单的内容,您可以将其提供给 Awk 或 Perl 进行进一步处理。为了稳健性,您可能想要输出以 null 分隔的字段,但常规的非 GNU Awk 无法可靠地处理这些字段,因此可能会使用 Perl。这是一个稍微快速但肮脏的尝试:
git log --format=format:'title:%h%x00description:%s%x00author:%an%x00pubDate:%ad%x00' |
perl -0ne 'BEGIN {
print("<?xml version="1.0" ?><rss version="2.0"><channel>\n");
}
@s = /^([^:]+):(.*)/;
$f[$i] = $s[0]; $fld[$i] = $s[1];
# Escape XML specials &<>
$fld[$i] =~ s/&/\&/g; $fld[$i] =~ s/</\</g; $fld[$i] =~ s/>/\>/g;
# Print when we have gathered a full record
if ($i++ == 3) { print "<item>\n";
for my $field (0..$i-1) {
print(" <$f[$field]>$fld[$field]</$f[$field]>\n");
} print "</item>\n";
@f = @fld = (); $i = 0 }
END { print("</channel></rss>\n"); }' >/tmp/text.xml
关于xml - bash 读取 git 日志并将其打印为 .xml 格式 (RSS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29127493/