Запутанность синтаксиса команды Cryptic sed - PullRequest
0 голосов
/ 30 декабря 2018

Может кто-нибудь объяснить, как эта команда sed работает здесь?

pkg info | sed -e 's/\([^.]*\).*/\1/' -e 's/\(.*\)-.*/\1/'

Эта команда удаляет номера версий из пакетов и печатает в стандартный вывод вот так

yajl-2.1.0                     Portable JSON parsing and serialization library in ANSI C
youtube_dl-2018.12.03          Program for downloading videos from YouTube.com
zathura-0.4.1                  Customizable lightweight pdf viewer
zathura-pdf-poppler-0.2.9_1    Poppler render PDF plugin for Zathura PDF viewer
zip-3.0_1                      Create/update ZIP files compatible with PKZIP
zsh-5.6.2                      The Z shell

и превращается в эту

yajl
youtube_dl
zathura
zathura-pdf-poppler
zip
zsh

Но мне трудно разобраться в деталях ([^.]*\).* \(.*\)-.*.Я понимаю случай \, -e, s.Но эти подстановочные знаки здесь кажутся очень загадочными.

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

Трудно сказать:
Удалите все подстроки, начинающиеся с точки или переноса.
Часть перед разделителем сопоставляется и запоминается.
Альтернативы:

# Incorrect: removes from first, not last hypen:
#    pkg info | sed 's/[-.].*//'
#    pkg info | cut -d "-" -f1 | cut -d"." -f1
#    pkg info | awk -F "-|[.]" '{print $1}'
# The dot is not needed when you remove the substring starting with the last hypen
pkg info | sed 's/-[^-]*$//'
pkg info | rev | cut -d"-" -f2- | rev
pkg info | awk -F "[.]" '{print $1}' | awk -F "[-]" -vOFS='-' 'NF>1 { NF--;print;}'
0 голосов
/ 01 января 2019
  1. Глупый невидимый текст GNU grep метод, который работает на консоли, но который потерпит неудачу, если он будет отправлен в файл или передан в фильтр:

    pkg info | GREP_COLORS='ms=30;30;30' grep '\-[^-]*\s.*$'
    

    Как это работает: grep используется для поиска последнего дефиса перед пробелом и всего, что после этого ( т.е. всего, что мы не хотим видеть), что grep отображается выделенными цветами, как определено в переменной среды GREP_COLORS.Поскольку выделенные цвета 30;30;30 - это черный шрифт (на черном фоне), нежелательный текст невидим.

    Если фон терминала уже черный, GREP_COLORS='ms=30 будет достаточно.

  2. sed метод, основанный на не печати grep регулярное выражение :

    pkg info | sed 's#\(^.*\)\(-[^-]*[[:space:]].*$\)#\1#'
    

    ... этот метод можно отправить на трубы и фильтры.Укороченная версия с использованием GNU sed:

    pkg info | sed 's#\(^.*\)\(-.*\s.*\)#\1#'
    
0 голосов
/ 30 декабря 2018

В вашем регулярном выражении ([^.]*\).*, (, который фактически равен \(, является началом захвата группы , а затем [^.]* захватывает каждый символ, кроме буквальной точки, а * означает нольили более, тогда \) - это отметка закрытия группы , которую мы начали, затем .* захватывает все, что осталось после захвата group1 .

Аналогично будетобъяснение для \(.*\)-.* regex, где \(.*\) будет жадно захватывать все в захвате group , но остановится на последнем дефисе -, а затем будет соответствовать дефису, а далее .* будет соответствовать оставшемуся тексту.1022 *

Чтобы объяснить на примере, давайте возьмем youtube_dl-2018.12.03.

Здесь \([^.]*\) будет захватывать все до точки, следовательно, он будет захватывать youtube_dl-2018, а затем оставшиеся .* будут захватывать .12.03.Затем он будет заменен на \1, что означает, что youtube_dl-2018 будет передано следующему регулярному выражению -e 's/\(.*\)-.*/\1/'.

Затем во втором регулярном выражении \(.*\)-.*, \(.*\) захватит youtube_dl ивведите group1 , потому что после этого есть дефис и .* захватит оставшийся текст, который является 2018.И так как он заменен на \1, следовательно, окончательный текст станет youtube_dl.

Видя ваши данные, я полагаю, вы также можете упростить вашу команду до этого, так как ваш первый регулярное выражение в команде sed кажетсяизлишний.Попробуйте эту следующую команду и посмотрите, выводит ли она тот же результат?

pkg info | sed -e 's/\(.*\)-.*/\1/'

Вы можете использовать только эту упрощенную команду, поскольку ни один из ваших данных не содержит . перед -, в противном случае вам следует использоватьсобственная команда, которая имеет два sed правила.

Также, на другой ноте, если вы используете -r, (или -E для OS X ),для расширенного регулярного выражения вам не нужно избегать скобок, и вы можете записать свое регулярное выражение как

pkg info | sed -r 's/([^.]*).*/\1/' -r 's/(.*)-.*/\1/'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...