líneas grep después del partido hasta el final


12

Tengo el siguiente resultado de git status, ¿cómo hago greppara todo despué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]$ 

Así, pero sin especificar el número de líneas, como el -Aparámetro en 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]$ 

¿Hay una manera de hacerlo?

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

¿Por qué no puedes usar -Aun número lo suficientemente grande como argumento?
Kasperd

Respuestas:


17

Con GNU grep(probado con la versión 2.6.3):

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

Se utiliza -Ppara expresiones regulares perl, -zpara coincidir también con la nueva línea \ne -oimprimir solo lo que coincide con el patrón.

La expresión regular explicó :

Primero hacemos coincidir cualquier carácter ( .) cero o varias veces ( *) hasta que ocurra la secuencia Untracked files. Ahora, la parte dentro de los corchetes (.*\n)coincide con cualquier carácter, excepto una nueva línea ( .) cero o varias veces ( *) seguido de una nueva línea ( \n). Y todo eso (que está dentro de los backets) puede ocurrir cero o varias veces; Ese es el significado de lo último *. Ahora debería coincidir con todas las demás líneas, después de la primera aparición de Untracked files.


3
Una respuesta que realmente usa grep, ¡estoy impresionado!
Hyppy

@hyppy yo también) y, de nuevo, el partido también evolucionó Perl regex)
alexus

1
Esto no funciona bien si la entrada tiene muchas líneas. Lo probé en Ubuntu 14.04, y si la coincidencia es más larga que aproximadamente 8000 líneas, se produce una falla.
Kasperd

2
@kasperd Creo que con más de 8000 líneas, grepno es la herramienta correcta. Pero de lo contrario, esta pregunta es (creo) para que el usuario vea solo la salida relevante, lo que obviamente no tiene en más de 8000 líneas, greped o no.
caos

1
@chaos También probé grep -A999999999 'Untracked files'con 1000000 líneas antes del partido y 1000000 líneas después del partido. Ese enfoque funcionó bien. Entonces greppuede hacerlo. El problema con su enfoque es que lo está obligando a realizar una sola coincidencia en todo el archivo en lugar de en líneas individuales.
Kasperd

13

Si no te importa usar sed, aquí hay una posible solución

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

Esto tiene la ventaja de que funciona con grep y sed de UNIX, mientras que la solución aceptada requiere grep de GNU.
Guntram Blohm apoya a Monica

3

Yo usaría awkpara esto:

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

Esta /Untracked files/,0es una expresión de rango. Se evalúa como verdadero desde la primera vez Untracked filesy hasta0 evalúa como verdadero. Como esto nunca sucede, imprime el resto del archivo.

Tenga en cuenta que awkel comportamiento de un Verdadero es imprimir el registro actual (línea, normalmente), es por eso que no tenemos que llamar explícitamente print.


2

Puedes probar:

git status | grep -A99 Untracked

donde -Aimprimiría líneas de contexto final después del partido.

Alternativamente, use moreo less, por ejemplo:

git status | less +/Untracked

Para fines de secuencias de comandos, usaría ex/ vi:

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

Para incluir una línea con archivos sin seguimiento , use en kd1Glugar de d1G.

O sin tubería y /dev/stdin, la sintaxis sería: ex ... <(git status).


Lo incluí -Aen mi pregunta original, pero me gusta more +/Untrackedparte de su respuesta.
alexus

@alexus Si está escribiendo un script, he agregado la versión con la excual es equivalente vi -e.
kenorb

gracias, creo more/ lesses muy útil)
alexus

1

Para una línea con paréntesis para generar una subshell para evitar retener las variables:

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

Simplemente puede canalizar al final de eso en cualquier otra cosa que necesite hacer con él.

O puede usarlo en cualquier script de shell

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

Reemplace el echo "$LINE"con lo que quiera hacer con los datos. Si desea omitir la línea "Archivos no rastreados", simplemente cambie las dos pruebas.


0

puede usar algo como esto, usé Perl, el siguiente conjunto de comandos count = 1si hago coincidir alguna cadena en la línea actual y cuando el ciclo while finaliza, verifico las variables de conteo e imprimo el rango de líneas desde el lugar donde coinciden hasta el último línea

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
Demasiado complicado. Una solución Perl simple está aquí: stackoverflow.com/a/18167194/111036 . Una variación que incluye la línea para que coincida podría ser:perl -ne 'print if /Untracked files:/ .. 0'
mivk
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.