簡體   English   中英

管道后如何在子殼內使用while循環

[英]How to use while loop inside subshell after pipe

我一直在尋找解決方案,但是找不到任何直接解決我問題的方法。 我正在嘗試將某些作者在git repo中添加和刪除的行加起來。 我正在使用git log通過管道傳輸到sed,通過管道傳輸到awk,現在我試圖通過管道傳輸到子外殼以將數字相加。 問題在於,在子shell中無法正確解釋管道輸入,並且我不知道為什么。 我懷疑它處於while循環中,因為subshel​​l語法的性質以及對分號的挑剔性。

我在子外殼中移動了代碼,添加和刪除了分號,使用反斜杠進行行分隔以查看是否是問題所在,但都沒有起作用。 我不太精通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

您的代碼嘗試生成兩次人類可讀的輸出:一次進入awk,另一次進入bash。 由於awk生成的輸出是輸入到bash ,這意味着您試圖通過管道傳遞供人類使用的輸出格式,並像將其作為供機器使用的輸入格式一樣讀取它; 顯然不是。

完全沒有理由采用這種方法:在同一過程中生成所有人類可讀的輸出。

#!/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"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM