我已经寻找并找到了解决方案,但是找不到任何直接解决我的问题的方法。我正在尝试将某些作者在git repo中添加和删除的行加起来。我正在使用git log通过管道传输到sed,通过管道传输到awk,现在我试图通过管道传输到子外壳以将数字相加。问题在于,在子shell中无法正确解释管道输入,并且我不知道为什么。我怀疑它处于while循环中,因为subshell语法的性质以及对分号的挑剔。
我在子shell内移动了代码,添加和删除了分号,使用反斜杠进行行分隔以查看是否是问题所在,但没有一个起作用。我不太精通Shell,因此对于经验丰富的人来说,这可能是一个显而易见的问题。 “ $ author”只是命令行中的第n个位置参数。
for author; do
echo "Listing file and line changes for $author"
git log --shortstat --author="$author" ${date:+--since="$date"} \
| sed -n -e '/files\? changed/s/, /\n/gp' \
| awk '
$3=="changed" {changed+=$1}
$2=="deletions(-)" {deletions+=$1}
$2=="insertions(+)" {insertions+=$1}
END{
print "files changed:", changed,
" lines removed:", deletions,
" lines added:", insertions,
" net change:", insertions-deletions
}'
done | {
total_changed=0
total_added=0
total_removed=0
while read changed insertions deletions; do
let total_changed+=changed
let total_added+=insertions
let total_removed+=deletions
done
echo "totals:"
echo "files changed: $total_changed"
echo "lines added: $total_added"
echo "lines removed: $total_removed" ;
}
最后一部分应该输出总计,但输出0。我还会遇到一些奇怪的语法错误。这是输出(输入是“ Benjamin Hills”):
/home/bhills/./git-log-lines-removed.sh: line 65: let: and line changes for Benjamin Hills: syntax error in expression (error token is "line changes for Benjamin Hills")
/home/bhills/./git-log-lines-removed.sh: line 64: let: changed:: syntax error in expression (error token is ":")
/home/bhills/./git-log-lines-removed.sh: line 65: let: 61 lines removed: 1345 lines added: 246 net change: -1099: syntax error in expression (error token is "lines removed: 1345 lines added: 246 net change: -1099")
totals:
files changed: 0
lines added: 0
lines removed: 0
答案 0 :(得分:0)
您的代码正在尝试生成人类可读的输出两次:一次进入awk,另一次进入bash。由于awk
生成的输出是输入到bash
的,这意味着您试图通过管道传递给人类的输出格式,并像对待机器的输入格式一样读取它。显然不是。
完全没有理由采用这种方法:在同一过程中生成人类可读的输出 all 。
#!/usr/bin/env bash
# ^^^^- NOT /bin/sh
total_changed=0
total_deletions=0
total_insertions=0
for author; do
changed=0; deletions=0; insertions=0
# Loop over output from "git log" for a single author
while read added deleted _; do
(( ++changed )) # each line is a file changed
{ [[ $added = - ]] || [[ $deleted = - ]]; } && continue # skip binary files
(( insertions += added ))
(( deletions += deleted ))
done < <(git log --numstat --format='' --author="$author" ${date:+--since="$date"})
# Print results from that author
printf '%s\n' "For author: $author" \
" Files changed: $changed" \
" Deletions: $deletions" \
" Insertions: $insertions"
# Add to totals
(( total_changed+=changed ))
(( total_deletions+=deletions ))
(( total_insertions+=insertions ))
done
# Print those totals
printf '%s\n' "Totals:" \
" Files changed: $total_changed" \
" Deletions: $total_deletions" \
" Insertions: $total_insertions"