linhas grep após partida até o final

12

Tenho a seguinte saída de git status, como faço greppara tudo depois 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]$ 

Assim, mas sem especificar o número de linhas, como o -Aparâmetro no 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]$ 

Existe uma forma de fazer isso?

[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
fonte
Por que você não pode usar -Aum número suficientemente grande como argumento?
Kasperd # 29/15

Respostas:

17

Com o GNU grep(testado com a versão 2.6.3):

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

Utiliza -Pexpressões regulares perl, -ztambém para combinar nova linha com \ne -oimprimir apenas o que corresponde ao padrão.

O regex explicou :

Primeiro, combinamos qualquer caractere ( .) zero ou várias vezes ( *) até uma ocorrência da string Untracked files. Agora, a parte dentro dos colchetes (.*\n)corresponde a qualquer caractere, exceto uma nova linha ( .) zero ou várias vezes ( *) seguida por uma nova linha ( \n). E tudo isso (dentro dos backets) pode ocorrer zero ou várias vezes; esse é o significado do último *. Agora deve corresponder a todas as outras linhas, após a primeira ocorrência de Untracked files.

caos
fonte
3
Uma resposta que realmente usa grep, estou impressionado!
Hyppy
@hyppy me também) e, em seguida, mais uma vez, corresponder também evoluiu regex Perl)
alexus
1
Isso não funciona bem se a entrada tiver muitas linhas. Eu testei no Ubuntu 14.04 e, se a correspondência for maior que cerca de 8000 linhas, ela será segmentada.
Kasperd # 29/15
2
@ Kasperd Eu acho que com mais de 8000 linhas, grepnão é a ferramenta certa. Mas, caso contrário, essa pergunta é (eu acho) para o usuário ver apenas a saída relevante, o que você obviamente não tem em mais de 8000 linhas, editadas grepou não.
caos
1
@chaos Também testei grep -A999999999 'Untracked files'com 1000000 linhas antes da partida e 1000000 linhas após a partida. Essa abordagem funcionou muito bem. Então greppode fazê-lo. O problema com sua abordagem é que você está forçando a executar uma única correspondência em todo o arquivo, e não em linhas individuais.
Kasperd # 29/15
13

Se você não se importa em usar o sed, aqui está uma solução possível

git status | sed -n -e '/Untracked files/,$p'
rahul
fonte
Isso tem a vantagem de funcionar com grep e sed simples do UNIX, enquanto a solução aceita requer o grep do GNU.
Guntram Blohm apoia Monica
3

Eu usaria awkpara isso:

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

Esta /Untracked files/,0é uma exressão de intervalo. Ele avalia como True desde a primeira vez Untracked filese até 0avalia como True. Como isso nunca acontece, ele imprime o restante do arquivo.

Observe que awko comportamento de um True é imprimir o registro atual (linha, normalmente), é por isso que não precisamos chamar explicitamente print.

fedorqui
fonte
2

Você pode tentar:

git status | grep -A99 Untracked

onde -Aimprimiria linhas do contexto à direita após a partida.

Como alternativa, use moreou less, por exemplo:

git status | less +/Untracked

Para fins de script, eu usaria ex/ vi:

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

Para incluir linha com arquivos não rastreados , use em kd1Gvez de d1G.

Ou sem tubulação e /dev/stdin, a sintaxe seria: ex ... <(git status).

kenorb
fonte
Incluí -Ana minha pergunta original, mas gosto de more +/Untrackedparte da sua resposta.
Alexus 29/05
@alexus Se você estiver escrevendo um script, adicionei a versão exequivalente à vi -e.
Kenorb 29/05
obrigado, eu acredito more/ lessé muito útil)
alexus
1

Para uma linha única entre parênteses gerar um subshell, assim você evita manter as variáveis:

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

Você pode simplesmente inserir no final disso tudo o que precisar fazer.

Ou você pode usá-lo em qualquer script de shell

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

Substitua por o echo "$LINE"que você deseja fazer com os dados. Se você quiser pular a linha "Arquivos não rastreados", basta alternar os dois testes.

Hyppy
fonte
0

você pode usar algo assim, usei Perl, o seguinte comando definido count = 1se eu corresponder a alguma string na linha atual e quando o loop while terminar, verifico as variáveis ​​de contagem e imprimo o intervalo de linhas de onde a correspondência aconteceu até a última linha

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
fonte
1
Muito complicado. Uma solução Perl simples está aqui: stackoverflow.com/a/18167194/111036 . Uma variação que inclui a linha a corresponder pode ser:perl -ne 'print if /Untracked files:/ .. 0'
mivk 23/07