Действительно ли возможно создать многострочную строковую переменную в Make-файле

Поскольку Google возвращает этот SO-запрос поверх результатов для tempered greedy token, я чувствую себя обязанным предоставить более полный ответ.

Что такое закаленный жадный токен?

Ссылка rexegg.com tempered greedy token довольно кратка:

В (?:(?!{END}).)* квантор * применяется к точке, но теперь это закаленная точка. Отрицательный lookhhead (?!{END}) утверждает, что то, что следует за текущей позицией, не является строкой {END}. Поэтому точка никогда не сможет сопоставить открывающую фигуру {END}, гарантируя, что мы не будем перепрыгивать через разделитель {END}.

blockquote>

То есть: умеренный жадный token является своего рода отрицательным символьным классом для последовательности символа (см. отрицательный класс символов для single характер ).

ПРИМЕЧАНИЕ. Разница между умеренным жадным токеном и классом отрицательных символов заключается в том, что первый не соответствует тексту, отличному от самой последовательности, но single character , который не запускает эту последовательность. То есть (?:(?!abc|xyz).)+ не будет соответствовать def в defabc, но будет соответствовать def и bc, поскольку a запускает запрещенный abc и bc этого не делает.

Он состоит из:

  • (?:...)* - количественная группа, не захватывающая захват (это может быть группа захвата, но она не имеет смысла захватывать каждый отдельный символ) (* может быть +, это зависит от того, будет ли ожидаться пустая строка)
  • (?!...) - отрицательный результат, который фактически налагает ограничение на значение справа от текущего местоположения
  • . - (или любой (обычно одиночный) символ) шаблон потребления.

Однако мы всегда можем дополнительно умерить токен, используя чередование в негативном представлении (например, (?!{(?:END|START|MID)})) или заменяя точку совпадения символом с отрицательным символьным классом (например, (?:(?!START|END|MID)[^<>]) при попытке сопоставить текст только внутри тегов).

Распределение расходной части

Обратите внимание, что не упоминается конструкция, в которой потребляющая часть (точка в ориге inal tempered greedy token) помещается до . Ответ Авинаша ясно объясняет эту часть: (.(?!))* сначала сопоставляет любой символ (но новую строку без модификатора DOTALL), а затем проверяет, не следует ли ему , что приводит к сбою e в

table
.

Когда использовать умеренный жадный токен?

Rexegg.com дает идею:

  • Если мы хотим сопоставить блок текста между разделителем 1 и разделителем 2 без промежуточной подстроки 3 (например, {START}(?:(?!{(?:MID|RESTART)}).)*?{END}
  • Если мы хотим сопоставить блок текста, содержащий специфический шаблон внутри без переполнения последующих блоков (например, вместо ленивого совпадения точек, как в .*?chair.*?
    , мы будем использовать что-то вроде (?:(?!chair|).)*chair(?:(?!
    ).)*
    ).
  • Когда мы хотим совместить кратчайшее возможное окно между двумя строками. Лестное совпадение не поможет, когда вам нужно получить abc 2 xyz из abc 1 abc 2 xyz (см. abc.*?xyz и abc(?:(?!abc).)*?xyz ).

Проблема с производительностью

Закаленный жадный токен является ресурсоемким, так как контрольная проверка выполняется после каждого символ, сопоставляемый с шаблоном потребления. Развертывание техники цикла может значительно увеличить умеренную производительность алгоритма.

Скажем, мы хотим сопоставить abc 2 xyz в abc 1 abc 2 xyz 3 xyz . Вместо проверки каждого символа между abc и xyz с помощью abc(?:(?!abc|xyz).)*xyz мы можем пропустить все символы, которые не являются a или x, с [^ax]*, а затем соответствуют всем a, за которыми не следуют bca(?!bc)) и все x, за которыми не следует yzx(?!yz)): abc[^ax]*(?:a(?!bc)[^ax]*|x(?!yz)[^ax]*)*xyz .

110
задан jonner 16 March 2009 в 04:15
поделиться

6 ответов

Да, можно использовать определить ключевое слово для объявления многострочной переменной, как это:

define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.

It can be downloaded from $(DOWNLOAD_URL).

etc, etc.
endef

хитрая часть вытаскивает Вашу многострочную переменную назад из make-файла. Если Вы просто сделаете очевидную вещь использования "$ эха (ANNOUNCE_BODY)", то Вы будете видеть результат, который другие отправили здесь - оболочка пытается обработать вторые и последующие строки переменной как сами команды.

Однако можно экспортировать значение переменной как есть в оболочку как переменная среды и затем сослаться на него от оболочки как переменная среды (НЕ сделать переменная). Например:

export ANNOUNCE_BODY
all:
    @echo "$ANNOUNCE_BODY"

Примечание использование $ANNOUNCE_BODY, указывая на ссылку на переменную среды оболочки, а не $(ANNOUNCE_BODY), который был бы постоянным клиентом, делает ссылку на переменную. Также обязательно используйте кавычки вокруг Вашей ссылки на переменную, удостоверьтесь, что новые строки не интерпретируются самой оболочкой.

, Конечно, этот конкретный прием может быть платформой и чувствительной оболочкой. Я протестировал его на Ubuntu, который Linux с GNU колотит 3.2.13; YMMV.

160
ответ дан Eric Melski 5 November 2019 в 10:03
поделиться

Едва ли полезный ответ, но только указать, которые 'определяют', не работает, как отвечено Топором (не вписался в комментарий):

VERSION=4.3.1
PACKAGE_NAME=foobar
DOWNLOAD_URL=www.foobar.com

define ANNOUNCE_BODY
    Version $(VERSION) of $(PACKAGE_NAME) has been released
    It can be downloaded from $(DOWNLOAD_URL)
    etc, etc
endef

all:
    @echo $(ANNOUNCE_BODY)

Это дает ошибку, которой не может быть найдена команда 'It', таким образом, это пытается интерпретировать вторую строку, ОБЪЯВЛЯЮТ О ТЕЛЕ как о команде.

0
ответ дан Roalt 5 November 2019 в 10:03
поделиться

Да. Вы выходите из новых строк с \:

VARIABLE="\
THIS IS A VERY LONG\
TEXT STRING IN A MAKE VARIABLE"

обновление

А-ч, Вы хотите новые строки? Тогда не я не думаю, что существует любой путь в ванили, Делают. Однако можно всегда использовать здесь-документ в части

команды [Это не работает, видит комментарий от MadScientist]

foo:
    echo <<EOF
    Here is a multiple line text
    with embedded newlines.
    EOF
3
ответ дан mpe 5 November 2019 в 10:03
поделиться

Почему Вы не используете \n символ в своей строке для определения конца строки? Также добавьте дополнительную обратную косую черту для добавления его по нескольким строкам.

ANNOUNCE_BODY=" \n\
Version $(VERSION) of $(PACKAGE_NAME) has been released \n\
\n\
It can be downloaded from $(DOWNLOAD_URL) \n\
\n\
etc, etc"
1
ответ дан Roalt 5 November 2019 в 10:03
поделиться
-

Это работало для меня:

ANNOUNCE_BODY="first line\\nsecond line"

all:
    @echo -e $(ANNOUNCE_BODY)
0
ответ дан 24 November 2019 в 03:14
поделиться
Другие вопросы по тегам:

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