найдите первую строку, начинающуюся <с ключевого слова> после <другого-ключевого-слова>

Передайте строки по каналу через sort -n -r -k2. Отредактированный к виду от самого большого до самого маленького.

3
11.07.2011, 14:22
3 ответа

Я не уверен, как Вы сделаете это с grep, но для таких задач я предпочитаю awk. Это передает большему количеству управления, что я хочу сделать. хотя я не опытен в awk, и все еще учащий лишь вот то, как я достиг бы этого.

PKGNAM="package-name"; awk "/$PKGNAM\$/,/requires:/ { if ( \$0 ~ /requires:/ ) { sub( /^requires:.?/, \"\"  ); print } }"

ОБНОВЛЕНИЕ: обновленный пример awk команда, теперь это использует переменную PKGNAM для соответствия имени pacakge.

enter image description here

HTH.

5
27.01.2020, 21:10
  • 1
    хороший ответ, я проголосую за Вас, когда я буду иметь достаточно репутации (или приму Ваш ответ, если это будет лучшим через некоторое время). только для прояснения необходимо записать/package-name$ / поскольку существует много соответствий между пакетами (как GConf2 & GConf2-devel). А-ч –  Philomath 11.07.2011, 17:16
  • 2
    одна проблема, хотя, как я могу заменить имя пакета переменной? (Я должен использовать его в сценарии), расширение var не работает при окружении одинарными кавычками, и двойные кавычки портят awk сценарий. –  Philomath 11.07.2011, 17:38
  • 3
    Посмотрите, что я сказал Вам, что должны быть лучшие способы сделать его, и Gilles уже сказал Вам 4 потрясающих различных способа сделать это. Я обновил свой ответ также для демонстрации использования имени переменной. –  Hameedullah Khan 11.07.2011, 22:48
  • 4
    благодарит за всех, кто ответил, я просто люблю простоту этого ответа. KISS! –  Philomath 17.07.2011, 03:26

Grep рассматривает все строки независимо, таким образом, он не может сделать задания самостоятельно.

Awk является общим инструментом обработки текста. Отслеживайте то, что текущий пакет (в переменной p), и вывод соответствие, если a requires: строка найдена в правильном пакете (удаляющий requires: префикс).

<setup.ini awk -vpackage='NAME_OF_PACKAGE' '
    sub(/^@ */,"") {p=$0}
    p==package && sub(/^requires: */,"") {print}
'

Другой подход awk должен обработать вход, разграниченный новой строкой -@ последовательности, а не новые строки. Или, так как разделы пакета имеют пустую строку между ними, обрабатывают введенный абзацем: передайте пустую строку как разделитель записей RS (что означает, что записи разделяются одним или несколькими пустая строка). Затем для каждой строки в популярной записи, если строка начинается requires:, распечатайте его (минус префикс).

<setup.ini awk -vpackage='NAME_OF_PACKAGE' -vRS= -vFS='\n' '
    sub(/^@ */,"") && $1==package {
        for (i=2; i<NF; i++) {if (sub(/^requires: */,"",$i)) print $i}
    }'

Другая возможность является режимом абзаца Perl (-00). Если абзац запускается с правильного заголовка (/REGEXP/m означает многострочное соответствие, так, чтобы $ привязка означает конец строки, а не конец строки), и это содержит a requires: строка, затем распечатайте ту строку (минус префикс).

<setup.ini package=NAME_OF_PACKAGE perl -00 -ne '
    /\A@ *$ENV{package}$/m and /^requires: *(.*)$/m and print "$1\n"'

И вот один для (GNU) sed любители. (Вы, как ожидают, не поймете это.)

sed -ne '/^@/ { h; b; }; G; s/^requires: *\(.*\)\n@ *NAME_OF_PACKAGE$/\1/p'
3
27.01.2020, 21:10
  • 1
    , ничего себе! это волшебно! У меня определенно есть много для изучения. просто сувениры, кто из них, как ожидают, будет самым быстрым?, мы говорим приблизительно тысячи пакетов. –  Philomath 11.07.2011, 18:05
  • 2
    @Pilomath различие в скорости будет незначителен. Тысячи не очень для компьютера. Однако, если бы Вы собирались сделать это для каждого пакета, то это было бы намного быстрее для обработки их внезапно: поместите чтение и логику в той же программе (Perl, или Python был бы более соответствующим, чем оболочка). –  Gilles 'SO- stop being evil' 11.07.2011, 18:30
  • 3
    , конечно, но я - Просто Другой не - {Perl, Python} Хакер. –  Philomath 12.07.2011, 06:52

Вот a sed решение, которое может сделать это без обратной ссылки.

# cf. "3.3. Addressing and address ranges",
# http://sed.sourceforge.net/sedfaq3.html#s3.3 (esp. (6) Relentless. ...)

PKGNAME="package-name"
sed -ne '/^ *@ *'"${PKGNAME}"'/{
:a
N
/\n *requires: /!ba
s/.*\n *requires: *//
p
}' setup.ini 

Жабры (GNU) sed решения работают над Mac OS X 10.6.7 (использование FreeBSD sed) если b команда помещается на отдельную строку (или по крайней мере сопровождается разрывом строки).

PKGNAME="package-name"
sed -ne '/^ *@ *'"${PKGNAME}"'/{h
b
};G;s/^ *requires: *\(.*\)\n *@ *'"${PKGNAME}"' *$/\1/p' setup.ini
1
27.01.2020, 21:10
  • 1
    Хороший ответ, просто замените $ {PKGNAME} $ {PKGNAME }\\$, чтобы удостовериться, что GConf2 не соответствует GConf2-devel. –  Philomath 13.07.2011, 03:26

Теги

Похожие вопросы