lignes de grep après le match jusqu'à la fin


12

J'ai la sortie suivante de git status, comment puis-je greppour tout après 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]$ 

Comme ça, mais sans spécifier le nombre de lignes, comme le -Aparamètre dans 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]$ 

Y a-t-il un moyen de le faire?

[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]$ 

Pourquoi ne pouvez-vous pas utiliser -Aun nombre suffisant comme argument?
kasperd

Réponses:


17

Avec GNU grep(testé avec la version 2.6.3):

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

Utilise -Ples expressions régulières perl, -zpour faire correspondre la nouvelle ligne avec \net -opour imprimer uniquement ce qui correspond au motif.

L'expression régulière a expliqué :

D'abord, nous faisons correspondre n'importe quel caractère ( .) zéro ou plusieurs fois ( *) jusqu'à l'apparition de la chaîne Untracked files. Maintenant, la partie à l'intérieur des crochets (.*\n)correspond à n'importe quel caractère à l'exception d'un newline ( .) zéro ou plusieurs fois ( *) suivi d'un newline ( \n). Et tout cela (qui est à l'intérieur des backets) peut se produire zéro ou plusieurs fois; c'est le sens du dernier *. Il devrait maintenant correspondre à toutes les autres lignes, après la première occurrence de Untracked files.


3
Une réponse qui utilise réellement grep, je suis impressionné!
Hyppy

@hyppy moi aussi) et puis encore une fois, le match a également évolué Perl regex)
alexus

1
Cela ne fonctionne pas bien si l'entrée a beaucoup de lignes. Je l'ai testé sur Ubuntu 14.04, et si le match est plus long qu'environ 8000 lignes, il segfaults.
kasperd

2
@kasperd Je pense qu'avec 8 000+ lignes, ce grepn'est pas le bon outil. Mais sinon, cette question est (je pense) pour l'utilisateur de ne voir que la sortie pertinente, ce que vous n'avez évidemment pas à plus de 8000 lignes, grepéd ou non.
chaos

1
@chaos J'ai aussi testé grep -A999999999 'Untracked files'avec 1000000 lignes avant le match et 1000000 lignes après le match. Cette approche a très bien fonctionné. grepJe peux donc le faire. Le problème avec votre approche est que vous la forcez à effectuer une seule correspondance sur l'ensemble du fichier plutôt que sur des lignes individuelles.
kasperd

13

Si cela ne vous dérange pas d'utiliser sed, voici une solution possible

git status | sed -n -e '/Untracked files/,$p'

Cela a l'avantage de fonctionner avec grep et sed UNIX standard, tandis que la solution acceptée nécessite grep GNU.
Guntram Blohm prend en charge Monica

3

J'utiliserais awkpour cela:

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

Il /Untracked files/,0s'agit d'une expression de gamme. Il évalue à True dès la première fois Untracked fileset jusqu'à ce qu'il soit 0évalué à True. Comme cela ne se produit jamais, il imprime le reste du fichier.

Notez que awkle comportement d'un True est d'imprimer l'enregistrement en cours (ligne, normalement), c'est pourquoi nous n'avons pas à appeler explicitement print.


2

Vous pouvez essayer:

git status | grep -A99 Untracked

-Aimprimerait les lignes du contexte de fin après la correspondance.

Vous pouvez également utiliser moreou less, par exemple:

git status | less +/Untracked

À des fins de script, j'utiliserais ex/ vi:

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

Pour inclure une ligne avec des fichiers non suivis , utilisez à la kd1Gplace de d1G.

Ou sans tuyauterie et /dev/stdin, la syntaxe serait: ex ... <(git status).


J'ai inclus -Adans ma question d'origine, mais j'aime une more +/Untrackedpartie de votre réponse.
alexus

@alexus Si vous écrivez un script, j'ai ajouté la version exqui est équivalente à vi -e.
kenorb

merci, je crois more/ lessest très utile)
alexus

1

Pour qu'une ligne unique avec des parenthèses génère un sous-shell afin d'éviter de conserver les variables:

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

Vous pouvez simplement diriger à la fin de tout ce que vous devez faire avec.

Ou vous pouvez l'utiliser dans n'importe quel script shell

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

Remplacez le echo "$LINE"par ce que vous voulez faire avec les données. Si vous souhaitez ignorer la ligne "Fichiers non suivis", passez simplement les deux tests.


0

vous pouvez utiliser quelque chose comme ça, j'ai utilisé Perl, le jeu de commandes suivant count = 1si je fais correspondre une chaîne dans la ligne actuelle et lorsque la boucle while est terminée je vérifie les variables de comptage et j'imprime la plage de lignes à partir de laquelle la correspondance se produit jusqu'à la dernière ligne

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";}}'

1
Beaucoup trop compliqué. Une solution Perl simple est ici: stackoverflow.com/a/18167194/111036 . Une variation qui inclut la ligne à associer pourrait être:perl -ne 'print if /Untracked files:/ .. 0'
mivk
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.