grep Zeilen nach dem Spiel bis zum Ende

12

Ich habe folgende Ausgabe von git status, wie mache ich das grepfür alles nach Untracked files:

[alexus@wcmisdlin02 Test]$ git status 
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   app/.gitignore
#   new file:   app/app.iml
#   new file:   app/build.gradle
#   new file:   app/proguard-rules.pro
#   new file:   app/src/androidTest/java/org/alexus/test/ApplicationTest.java
#   new file:   app/src/main/AndroidManifest.xml
#   new file:   app/src/main/java/org/alexus/test/MainActivity.java
#   new file:   app/src/main/res/layout/activity_main.xml
#   new file:   app/src/main/res/menu/menu_main.xml
#   new file:   app/src/main/res/mipmap-hdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-mdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-xhdpi/ic_launcher.png
#   new file:   app/src/main/res/mipmap-xxhdpi/ic_launcher.png
#   new file:   app/src/main/res/values-w820dp/dimens.xml
#   new file:   app/src/main/res/values/dimens.xml
#   new file:   app/src/main/res/values/strings.xml
#   new file:   app/src/main/res/values/styles.xml
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   .gitignore
#   .idea/
#   Test.iml
#   build.gradle
#   gradle.properties
#   gradle/
#   gradlew
#   gradlew.bat
#   settings.gradle
[alexus@wcmisdlin02 Test]$ 

So, aber ohne Angabe der Anzahl der Zeilen, wie der -AParameter in GNU grep:

[alexus@wcmisdlin02 Test]$ git status | grep -A100 'Untracked files'
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   .gitignore
#   .idea/
#   Test.iml
#   build.gradle
#   gradle.properties
#   gradle/
#   gradlew
#   gradlew.bat
#   settings.gradle
[alexus@wcmisdlin02 Test]$ 

Gibt es eine Möglichkeit, dies zu tun?

[alexus@wcmisdlin02 Test]$ grep --version
grep (GNU grep) 2.20
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
[alexus@wcmisdlin02 Test]$ 
alexus
quelle
Warum können Sie nicht -Amit einer ausreichend großen Zahl als Argument verwenden?
Kasperd

Antworten:

17

Mit GNU grep(getestet mit Version 2.6.3):

git status | grep -Pzo '.*Untracked files(.*\n)*'

Verwendet -Pfür reguläre Perl-Ausdrücke, -zum auch Zeilenumbrüche mit dem Muster abzugleichen \nund -onur das zu drucken, was dem Muster entspricht.

Der Regex erklärte :

Zuerst vergleichen wir ein beliebiges Zeichen ( .) null oder mehrmals ( *), bis die Zeichenfolge vorkommt Untracked files. Jetzt entspricht der Teil in den Klammern einem (.*\n)beliebigen Zeichen mit Ausnahme einer neuen Zeile ( .), die null oder mehrmals ( *) gefolgt von einer neuen Zeile ( \n) ist. Und all das (das ist in den Backets) kann null oder mehrmals vorkommen; Das ist die Bedeutung des Letzten *. Nach dem ersten Auftreten von sollte es nun mit allen anderen Zeilen übereinstimmen Untracked files.

Chaos
quelle
3
Eine Antwort, die tatsächlich verwendet grep, ich bin beeindruckt!
Hyppy
@hyppy mich auch) und dann wieder, Match auch entwickelt Perl Regex)
Alexus
1
Dies funktioniert nicht gut, wenn die Eingabe viele Zeilen enthält. Ich habe es auf Ubuntu 14.04 getestet und wenn die Übereinstimmung länger als etwa 8000 Zeilen ist, segfaults es.
Kasperd
2
@kasperd Ich denke mit 8000+ Zeilen grepist das nicht das richtige Werkzeug. Aber ansonsten ist diese Frage (glaube ich) für den Benutzer nur die relevante Ausgabe zu sehen, was Sie offensichtlich bei 8000+ Zeilen nicht haben, greped oder nicht.
Chaos
1
@chaos habe ich auch grep -A999999999 'Untracked files'mit 1000000 Zeilen vor dem Match und 1000000 Zeilen nach dem Match getestet . Dieser Ansatz hat gut funktioniert. grepKann es also tun. Das Problem bei Ihrer Vorgehensweise besteht darin, dass Sie eine einzelne Übereinstimmung für die gesamte Datei und nicht für einzelne Zeilen erzwingen.
Kasperd
13

Wenn es Ihnen nichts ausmacht, sed zu verwenden, finden Sie hier eine mögliche Lösung

git status | sed -n -e '/Untracked files/,$p'
Rahul
quelle
Dies hat den Vorteil, dass es mit einfachem UNIX grep und sed funktioniert, während die akzeptierte Lösung GNU grep erfordert.
Guntram Blohm unterstützt Monica
3

Ich würde dafür verwenden awk:

git status | awk '/Untracked files/,0'

Dies /Untracked files/,0ist ein Bereichsausdruck. Er wertet True aus der ersten Zeit Untracked filesund bis 0True ergibt . Da dies niemals geschieht, wird der Rest der Datei gedruckt.

Beachten Sie, dass awkdas Verhalten von True das Drucken des aktuellen Datensatzes (normalerweise Zeile) ist. Aus diesem Grund müssen wir nicht explizit aufrufen print.

fedorqui
quelle
2

Sie können versuchen:

git status | grep -A99 Untracked

wo -Awürde Zeilen mit nachgestellten Kontext nach dem Spiel drucken.

Alternativ verwenden Sie moreoder less, zum Beispiel:

git status | less +/Untracked

Für Skriptzwecke würde ich ex/ verwenden vi:

git status | ex -s +"/Untracked/norm d1G" +%p -cq! /dev/stdin

Verwenden Sie anstelle von, um eine Zeile mit nicht verfolgten Dateien einzuschließen .kd1Gd1G

Oder ohne Verrohrung und /dev/stdinwürde die Syntax sein: ex ... <(git status).

Kenorb
quelle
Ich habe -Ain meine ursprüngliche Frage aufgenommen, aber ich mag einen more +/UntrackedTeil Ihrer Antwort.
Alexus
@alexus Wenn Sie ein Skript schreiben, habe ich die Version hinzugefügt, mit exder dies äquivalent ist vi -e.
Kenorb
Danke, ich glaube, more/ lessist sehr nützlich)
Alexus
1

Wenn ein Einzeiler mit Klammern eine Unterschale erzeugt, vermeiden Sie, die Variablen beizubehalten:

(while read LINE ; do [[ "$LINE" =~ "Untracked files" ]] && MATCHED=1 ; \
   [[ "$MATCHED" = 1 ]] && echo "$LINE" ; done < <(git status))

Sie können einfach am Ende davon in alles hineinpfeifen, was Sie sonst noch damit tun müssen.

Oder Sie können es in einem beliebigen Shell-Skript verwenden

while read LINE ; do
    [[ "$LINE" =~ "Untracked files" ]] && MATCHED=1
    [[ "$MATCHED" = 1 ]] && echo "$LINE"
done < <(git status)

Ersetzen Sie das echo "$LINE"durch das, was Sie mit den Daten tun möchten. Wenn Sie die Zeile "Untracked files" überspringen möchten, wechseln Sie einfach die beiden Tests.

Hyppy
quelle
0

Sie können so etwas verwenden, ich habe Perl verwendet, den folgenden Befehlssatz, count = 1wenn ich mit einer Zeichenfolge in der aktuellen Zeile übereinstimme, und wenn die while-Schleife abgeschlossen ist, überprüfe ich die Zählvariablen und drucke den Zeilenbereich aus, von dem die Übereinstimmung bis zum letzten erfolgt Linie

ls -al | perl -e '@LINES = (); $n = 0 ; $nline = 0; while(<>){ push(@LINES, $_); $n++; if($_ =~ m/mirror/i) { $count = 1; $nline = $. - 1 };};  if($count != 0){ foreach $i($nline..$n-1){ print "\t$LINES[$i]\n";}}'
c4f4t0r
quelle
1
Viel zu kompliziert. Eine einfache Perl-Lösung finden Sie hier: stackoverflow.com/a/18167194/111036 . Eine Variation, die die passende Zeile enthält, könnte sein:perl -ne 'print if /Untracked files:/ .. 0'
mivk