`wc -l`で1行の合計を取得するにはどうすればよいですか?


12

履歴内の特定のファイルの行数を示すためにgitエイリアスを追加しました:

[alias]
lines = !lc() { git ls-files -z ${1} | xargs -0 wc -l; }; lc

ただし、wc -l複数の合計を報告しているため、10万行を超える行がある場合は、それらの合計を報告してから先に進みます。次に例を示します。

<100k行(望ましい出力)

$ git lines \*.xslt
  46 packages/NUnit-2.5.10.11092/doc/files/Summary.xslt
 232 packages/NUnit-2.5.10.11092/samples/csharp/_UpgradeReport_Files/UpgradeReport.xslt
 278 total

> 100k行(にパイプする必要がありましたgrep "total"

$ git lines \*.cs | grep "total"
 123569 total
 107700 total
 134796 total
 111411 total
  44600 total

wc -l一連の小計ではなく、から真の合計を取得するにはどうすればよいですか?


stackoverflow.com/questions/2501402/…によると、問題はにありxargs、ではありませんwc。私はまだそれを修正する方法に興味があり、答えには良い解決策がありません。
エーリク14年

3
お使いのバージョンはオプションをwcサポートしてい--files0-fromますか?その後、次のことができます{ git ls-files -z ${1} | wc -l --files0-from=- ; }
マークプロトニック14年

@MarkPlotnickそれは答えに値すると思います。
テルドン

いや。wc: unrecognized option '--files0-from=-'
エーリク14年

回答:


12

これを試して、明白であることをおologiesびします:

cat *.cs | wc -l

または、gitで:

git ls-files -z ${1} | xargs -0 cat | wc -l

wc個々のカウントと合計の両方を使用awkして、出力を実際に出力のように見せたい場合は、を使用して個々の行を加算できます。

git ls-files -z ${1} | xargs -0 wc -l |
awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next}
     {total+=$1;print}
     END {print total,"total"}'

それはwcあなたにとって重要な場合には、それがするようにうまく並べられません。そのためには、入力全体を読み取って保存し、合計を計算してから、合計を使用してフィールド幅を計算してから、そのフィールド幅を使用して、記憶された行の書式付き出力を印刷する必要があります。家の改修プロジェクトのように、awkスクリプトは決して完成しません。

(熱心なエディターへの注意:最初のawk条件の正規表現は、名前が「total」で始まるファイルとスペースがある場合です。それ以外の場合、条件ははるかに単純かもしれません$2 == "total"。)


それは機能しますが、合計のみを出力します(git ls-files -z ${1} | xargs -0 cat | wc -l)。ただし、上記の最初の例のようにwc -lが提供するファイルごとの行カウントがありません。ここで両方の世界を最大限に活用する方法はありますか?
エーリク14年

または、それが難しすぎる場合、それが分割される場合のスイッチはどうですか:合計を与えるだけで、そうでない場合は、通常のwcをファイルごとに合計出力で与えますか?
エーリク14年

@Ehryk:一度だけgrep -v合計行を削除する方法と、合計合計を取得することを提案する方法の2回を実行できます。または、編集された回答のawkソリューションを試すことができます
リチ14

+1:「家の改修プロジェクトのように、awkスクリプトが実際に完成することはありません。」
エーリク14

それは魅力のように働いた。私の最終結果:git ls-files -z ${1} | xargs -0 wc -l | awk '/^[[:space:]]*[[:digit:]]+[[:space:]]+total$/{next} {total+=$1;print} END {print "\n Total:",total,"lines"}'
エーリック14

7

Linuxを実行している場合は、wcおそらくGNU Coreutilsから来ており、--files0-fromカウントするNULで終わるファイル名の任意の長いリストを含むファイル(またはstdin)を読み取るオプションがあります。GNUのCoreutils WCドキュメントはファイル名のリストがあれば、コマンドラインの長さ制限を超えることがあるときに便利である」と言う。それは粉々にリストを分割し、トイレのプリントを作るため、このようなケースでは、xargsのを経由してトイレを実行することは望ましくありませんリスト全体ではなく、各サブリストの合計。」

だからこれを試してください:

lc() { git ls-files -z ${1} | wc -l --files0-from=- ; } 

編集:あなたwcは最後の千年紀からであり、そのオプションがないので、awk「total」という名前のファイルがある場合とない場合を想定して、よりポータブルなソリューションを紹介します。の出力をフィルタリングwcし、total行を省略して代わりにそれらを合計し、最後に総計を出力します。

私が知らないことの1つは、gitエイリアスの実装に単一引用符$1$2内部引用符の問題があるかどうかです。これらの問題はにそのまま渡す必要がありますawk

lc() {
  git ls-files -z ${1} |
  xargs -0 wc -l |
  awk 'BEGIN { total=0; } { if (NF==2 && $2 == "total") total += $1; else print; } END { print total, "total"; }' ;
}

私はLinuxを実行していません。Gitfor Windowsのgit bashプロンプトにありますmsysgit.github.io(msysgit)。
エーリク14年

OK。でxargswcあなたが走っているのはCygwinからですか?の出力を貼り付けられますwc --versionか?
マークPlotnick 14年

彼らは完全なcygwinのインストールからじゃない:$ wc --version wc (GNU textutils) 2.0 Written by Paul Rubin and David MacKenzie. Copyright (C) 1999 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Ehryk

それはWindows実行可能ファイルでいっぱいですC:\Program Files (x86)\Git\bin\wc.exe
Ehryk 14年

@Ehryk MsysgitはLinuxツールの移植版ですが、古いバージョンを使用する傾向があるため、インストールされていない場合があります--files0-from
ジル 'SO-悪であるのをやめる' 14年

4

問題はxargs、コマンドを複数の実行に分割wcしているため、各時間の合計を報告していることです。いくつかのオプションがあり、物事をそのままにしてwc出力を解析できます。

git ls-files -z ${1} | xargs -0 wc -l | awk '/total/{k+=$1}END{print k,"total"}';

ファイルをcatすることができます:

git ls-files -z ${1} | xargs -0 cat | wc -l

または、xargs完全にスキップすることもできます(ここから適応):

unset files i; while IFS= read -r -d $'\0' name; do 
 files[i++]="$name"; 
done < <(git ls-files -z ${1} ) && wc -l "${files[@]}"

ただし、ファイルのリストがARG_MAXより長い場合、これは壊れます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.