grep строки после матча до конца

12

У меня есть следующий вывод git status, как я grepдля всего после 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]$ 

Вот так, но без указания количества строк, как -Aпараметр в 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]$ 

Есть ли способ сделать это?

[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
источник
Почему вы не можете использовать -Aс достаточно большим числом в качестве аргумента?
Касперд

Ответы:

17

С GNU grep(протестировано с версией 2.6.3):

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

Используется -Pдля регулярных выражений perl, -zтакже для соответствия новой строки \nи -oдля печати только того, что соответствует шаблону.

Регулярное выражение объяснило :

Сначала мы сопоставляем любой символ ( .) ноль или несколько раз ( *) до появления строки Untracked files. Теперь, часть в скобках (.*\n)соответствует любому символу, кроме newline ( .) ноль или несколько раз ( *), за которым следует newline ( \n). И все это (внутри бэкетов) может происходить ноль или несколько раз; в этом смысл последнего *. Теперь он должен соответствовать всем остальным строкам после первого появления Untracked files.

хаос
источник
3
Ответ, который на самом деле использует grep, я впечатлен!
Hyppy
@ также рад мне), а затем, снова, матч также развивал регулярное выражение Perl)
alexus
1
Это не работает, если на входе много строк. Я проверил его на Ubuntu 14.04, и если совпадение длиннее, чем около 8000 строк, то это происходит с ошибками.
Касперд
2
@kasperd Я думаю, с 8000+ строк, grepэто не правильный инструмент. Но в противном случае этот вопрос (я думаю) для пользователя, чтобы увидеть только соответствующий вывод, который вы, очевидно, не имеете на 8000+ строк, grepили нет.
хаос
1
@chaos Я также тестировал grep -A999999999 'Untracked files'1000000 строк перед матчем и 1000000 строк после матча. Этот подход работал просто отлично. Так grepможет сделать это. Проблема с вашим подходом заключается в том, что вы заставляете его выполнять одно сопоставление для всего файла, а не для отдельных строк.
Касперд
13

Если вы не возражаете против использования sed, вот возможное решение

git status | sed -n -e '/Untracked files/,$p'
Рахул
источник
Преимущество этого заключается в том, что он работает с простым UNIX grep и sed, в то время как для принятого решения требуется GNU grep.
Гунтрам Блом поддерживает Монику
3

Я бы использовал awkдля этого:

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

Это /Untracked files/,0выражение диапазона. Он оценивается как True с первого раза Untracked filesи до тех пор, пока не 0оценивается как True. Так как этого никогда не происходит, он печатает остальную часть файла.

Обратите внимание, что awkповедение True заключается в печати текущей записи (обычно строки), поэтому нам не нужно явно вызывать print.

fedorqui
источник
2

Вы можете попробовать:

git status | grep -A99 Untracked

где -Aбудет печатать строки конечного контекста после совпадения.

В качестве альтернативы используйте moreили less, например:

git status | less +/Untracked

Для сценариев я бы использовал ex/ vi:

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

Чтобы включить строку с неотслеживаемыми файлами , используйте kd1Gвместо d1G.

Или без трубопровода и /dev/stdinсинтаксис будет выглядеть так : ex ... <(git status).

kenorb
источник
Я включил -Aв свой оригинальный вопрос, но мне нравится more +/Untrackedчасть вашего ответа.
alexus
@alexus Если вы пишете скрипт, я добавил версию, с exкоторой эквивалентен vi -e.
Кенорб
спасибо, я считаю more/ lessочень полезно)
alexus
1

Для однострочного с круглыми скобками, чтобы порождать подоболочку, чтобы избежать сохранения переменных:

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

Вы можете просто передать в конце этого все, что вам нужно с этим делать.

Или вы можете использовать его в любом сценарии оболочки

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

Замените на echo "$LINE"то, что вы хотите сделать с данными. Если вы хотите пропустить строку «Untracked files», просто переключите два теста.

Hyppy
источник
0

Вы можете использовать что-то вроде этого, я использовал Perl, следующий набор команд, count = 1если я сопоставляю некоторую строку в текущей строке, и когда цикл while завершается, я проверяю переменные count и печатаю диапазон строк, из которых совпадение происходит с последним линия

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
источник
1
Слишком сложно. Простое решение Perl здесь: stackoverflow.com/a/18167194/111036 . Вариант, который включает в себя строку для сопоставления может быть:perl -ne 'print if /Untracked files:/ .. 0'
MIVK