linie grep po meczu do końca

12

Mam następujące dane wyjściowe git status, jak to zrobić greppo wszystkim 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]$ 

Tak, ale bez określania liczby wierszy, jak -Aparametr w 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]$ 

Czy jest na to sposób?

[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
źródło
Dlaczego nie możesz użyć -Awystarczająco dużej liczby jako argumentu?
kasperd

Odpowiedzi:

17

Z GNU grep(testowany z wersją 2.6.3):

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

Używa -Pwyrażeń regularnych perla, -zaby również dopasować znak nowej linii \ni -owydrukować tylko to, co pasuje do wzorca.

Wyrażenie regularne wyjaśniło :

Najpierw dopasowujemy dowolny znak ( .) zero lub wiele razy ( *) aż do wystąpienia ciągu Untracked files. Teraz część w nawiasach (.*\n)odpowiada dowolnemu znakowi oprócz znaku nowej linii ( .) zero lub wiele razy ( *), po którym następuje nowa linia ( \n). A wszystko to (to jest w tle) może wystąpić zero lub wiele razy; to jest znaczenie ostatniego *. Powinien teraz pasować do wszystkich innych linii po pierwszym wystąpieniu Untracked files.

chaos
źródło
3
grepJestem pod wrażeniem odpowiedzi, która naprawdę się przydaje!
Hyppy
@ hippy ja też), a potem znowu mecz ewoluował Perl regex)
alexus
1
Nie działa to dobrze, jeśli na wejściu jest dużo linii. Przetestowałem to na Ubuntu 14.04, a jeśli dopasowanie jest dłuższe niż około 8000 linii, następuje awaria.
kasperd
2
@kasperd Myślę, że przy ponad 8000 liniach grepnie jest to właściwe narzędzie. Ale w przeciwnym razie to pytanie (wydaje mi się), aby użytkownik widział tylko odpowiednie wyjście, czego oczywiście nie masz na 8000+ linii, greped lub nie.
chaos
1
@chaos Testowałem również grep -A999999999 'Untracked files'z 1000000 linii przed meczem i 1000000 linii po meczu. Takie podejście działało dobrze. Więc grepmogę to zrobić. Problem z twoim podejściem polega na tym, że zmuszasz go do wykonania pojedynczego dopasowania w całym pliku, a nie w poszczególnych liniach.
kasperd
13

Jeśli nie masz nic przeciwko użyciu sed, oto możliwe rozwiązanie

git status | sed -n -e '/Untracked files/,$p'
Rahul
źródło
Ma to tę zaletę, że działa ze zwykłym grepem i sedem w UNIXie, podczas gdy zaakceptowane rozwiązanie wymaga GNU grep.
Guntram Blohm wspiera Monikę
3

Użyłbym awkdo tego:

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

Jest /Untracked files/,0to wyjątek zasięgu. Ocenia się na Prawda od pierwszego razu Untracked filesi do czasu, aż 0dojdzie do Prawdy. Ponieważ tak się nigdy nie dzieje, drukuje resztę pliku.

Zauważ, że awkzachowanie do wartości True polega na drukowaniu bieżącego rekordu (normalnie liniowego), dlatego nie musimy jawnie wywoływać print.

fedorqui
źródło
2

Możesz spróbować:

git status | grep -A99 Untracked

gdzie -Awypisuje linie kontekstu końcowego po dopasowaniu.

Alternatywnie użyj morelub less, na przykład:

git status | less +/Untracked

Do celów skryptowych użyłbym ex/ vi:

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

Aby dołączyć linię do nieśledzonych plików , użyj kd1Gzamiast d1G.

Lub bez Rurociągi i /dev/stdinskładnia będzie: ex ... <(git status).

kenorb
źródło
Uwzględniłem -Amoje oryginalne pytanie, ale podoba mi się more +/Untrackedczęść twojej odpowiedzi.
Alexus
@alexus Jeśli piszesz skrypt, dodałem wersję, z exktórą jest on równoważny vi -e.
kenorb
dziękuję, uważam more/ lessjest bardzo przydatna)
Alex
1

Aby jedno-liniowy z nawiasami spawnował podpowłokę, aby uniknąć zachowywania zmiennych:

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

Na końcu możesz po prostu przeskoczyć do tego, co chcesz z tym zrobić.

Lub możesz użyć go w dowolnym skrypcie powłoki

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

Zamień na echo "$LINE"cokolwiek chcesz zrobić z danymi. Jeśli chcesz pominąć wiersz „Nie śledzone pliki”, po prostu przełącz dwa testy.

Hippy
źródło
0

możesz użyć czegoś takiego: użyłem Perla, następującego zestawu komend, count = 1jeśli dopasuję jakiś ciąg w bieżącej linii, a gdy pętla while zostanie zakończona, sprawdzam zmienne zliczania i wypisuję zakres linii, od których dopasowanie się stało do ostatniej linia

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
źródło
1
Zbyt skomplikowane. Proste rozwiązanie Perla znajduje się tutaj: stackoverflow.com/a/18167194/111036 . Wariacją zawierającą pasującą linię może być:perl -ne 'print if /Untracked files:/ .. 0'
mivk