Как сохранить новую строку без изменений в команде sed, используемой в Makefile (POSIX)? - PullRequest
5 голосов
/ 10 марта 2019

Примечание. Это не дубликат Возможно ли создать многострочную строковую переменную в Makefile и другие подобные вопросы.Этот вопрос требует POSIX-совместимых решений, которые не зависят от функций Bash-only или GNU Make-only.Другой вопрос о переполнении стека не имеет этого требования.

Возьмите этот сценарий оболочки, используя BSD sed в macOS High Sierra:

printf 'foo\nbaz\n' | sed '/foo/a\
bar
'

Вывод:

foo
bar
baz

Как я могу положить то же самое в Makefile?Вот что я пробовал, но, похоже, это не работает:

all:
    printf 'foo\nbaz\n' | sed '/foo/a\\
    bar\
    '

Это приводит к ошибкам:

$ make
printf 'foo\nbaz\n' | sed '/foo/a\\
/bin/sh: -c: line 0: unexpected EOF while looking for matching `''
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [all] Error 2

Как правильно написать приведенный выше вызов sed в Makefileтаким образом, что когда make выполняет цель all, он корректно передает косую черту и символы новой строки в оболочку?

Примечание. Я бы хотел, чтобы Makefile был совместимым с POSIX и использовал только функции из http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html.

Ответы [ 2 ]

5 голосов
/ 11 марта 2019

Расширение параметра с удалением суффикса в sed

Вот решение, которое помещает <newline>x (т.е. символ новой строки, за которым следует символ x) в переменную, а затем использует эту переменную в sed команда.При использовании этой переменной мы используем расширение параметра оболочки , чтобы избавиться от суффикса x, чтобы у нас остался только символ новой строки.

all:
    NX=$$(printf '\nx'); printf 'foo\nbaz\n' | sed "/foo/a\\$${NX%x}bar$${NX%x}"

Значение NX равно <newline>x, поэтому ${NX%x} оценивается как <newline>.Вот вывод:

$ make
NX=$(printf '\nx'); printf 'foo\nbaz\n' | sed "/foo/a\\${NX%x}bar${NX%x}"
foo
bar
baz

Упрощение расширения параметров в sed с помощью make макросов

Мы можем упростить использование предыдущего решения с помощью make макросов .Мы помещаем все громоздкие части в макросы.Затем мы расширяем эти макросы в командах оболочки.Вот пример:

NX = NX=$$(printf '\nx')
NL = $${NX%x}

all:
    $(NX); printf 'foo\nbaz\n' | sed "/foo/a\\$(NL)bar$(NL)"

Вот вывод:

$ make
NX=$(printf '\nx'); printf 'foo\nbaz\n' | sed "/foo/a\\${NX%x}bar${NX%x}"
foo
bar
baz

Расширение параметра с удалением суффикса до sed

Вот еще одно возможное решение для аналогичноголиний.Вместо того чтобы дважды записывать синтаксис ${NX%x} в команде sed, это упрощается путем присвоения самого ${NX%x} другой переменной оболочки с именем NL, и вместо нее в команде sed используется ${NL}.

all:
    NX=$$(printf '\nx'); NL=$${NX%x}; printf 'foo\nbaz\n' | sed "/foo/a\\$${NL}bar$${NL}"

Вот вывод:

$ make
NX=$(printf '\nx'); NL=${NX%x}; printf 'foo\nbaz\n' | sed "/foo/a\\${NL}bar${NL}"
foo
bar
baz

Упрощение расширения параметров до sed с make Макросами

Использование вышеуказанного решения может быть еще более упрощенос make макросами следующим образом:

NX = NX=$$(printf '\nx'); NL=$${NX%x}
NL = $${NL}

all:
     $(NX); printf 'foo\nbaz\n' | sed "/foo/a\\$(NL)bar$(NL)"

Вот вывод:

$ make
NX=$(printf '\nx'); NL=${NX%x}; printf 'foo\nbaz\n' | sed "/foo/a\\${NL}bar${NL}"
foo
bar
baz
0 голосов
/ 11 марта 2019

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

...