2015-06-23 4 views
2

Я портировании скрипт, написанный для Linux на FreeBSD, и наткнулся на эту строку:Портирование GNU СЭД команда BSD СЭД

local from_conf="$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1)" 

Он используется как часть функции, чтобы получить свойства из файл конфигурации ($ CONF), поэтому добавление фактических значений переменных может выглядеть примерно так:

local from_conf="$(sed -rn "s/^USERNAME=('|\"|)(.*)\1/\2/ip" "/etc/msm.conf" | tail -n 1)" 

под GNU SED (v4.2.2 в Ubuntu), это работает, как требуется, однако под BSD СЭД (он поставляется в FreeBSD 10.1) он жалуется:

sed: 1: "s/^USERNAME=('|"|)(.*)\ ...": RE error: empty (sub)expression

Кажется, что вторая труба в ('|"|) часть рисунка, удаляя ее (('|")), очищает ошибку, и я получаю желаемый результат на FreeBSD. Он также появляется, чтобы дать правильные результаты в Ubuntu, но так как я пытаюсь сделать код, переносимый между двумя системами, я хочу лучше понять эту часть выражения и почему он не работает под BSD sed ,


Мое понимание исходного шаблона (('|"|)) является:

Match:

  • одиночная кавычка (') - например, USERNAME = 'Foo'
  • двойные кавычки (") - например LOCALE =" бар»
  • ничего() - например, DELAY = 10

Как я могу порт этот шаблон для BSD, не нарушая его для GNU СЭД


Там еще один элемент, который не работает?

sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" 

\1 является частью шаблона, а под GNU sed будет вставлять любые результаты ('|\"|). Это не работает под BSD sed, есть ли другая переносная нотация? Или мне придется повторить первый шаблон дословно?


EDIT: Содержание /etc/msm.conf может выглядеть примерно так:

USERNAME='foo' 
LOCALE="bar" 
DELAY=10 
SERVER_NAME="Ben's Server" 

Ожидаемый выход sed -rn "s/^USERNAME=('|\"|)(.*)\1/\2/ip" "/etc/msm.conf" должен быть «foo».

+0

Можете ли вы предоставить примерную строку, которая соответствует ей, и ее результат при согласовании? – 123

+1

Я бы сказал, чтобы заменить '('| \" |) 'на' ([' "]?)', Но кажется, что пустота результата в том, что BSD 'sed' не похож на него, поэтому вряд ли это поможет. –

+0

Я собирался предложить то же самое. Может быть, BSD sed жалуется на пустое подвыражение в '(foo | bar |)', а не на '\ 1' пусто. Во всяком случае, стоит попробовать. – Wintermute

ответ

1

Это должно работать с первой группой захвата удалены

sed "s/^USERNAME=\(['\"]\)\{0,1\}\([^'\"]*\)['\"]\{0,1\}/\2/p;d" "/etc/msm.conf" 
+0

Это почти работает, вывод, который я получаю (если использовать образцы данных в моем редактировании OP), является' foo'' - см. Конечную одиночную кавычку. – forquare

+0

@forquare Попробуйте новый – 123

+0

Увы, это не работает для случая 'SERVER_NAME', который я добавил выше. Хотя в конфигурационном файле не должно быть таких случаев, было бы трудно исключить. Команда, запускаемая на 'SERVER_NAME', должна возвращать« сервер Бена », однако ваше редактирование возвращает« Bens Server ». – forquare

-2

Ваш вшита скрипт имеет плохой процитировать. Устраните внешние двойные кавычки следующим образом:

local from_conf=$(sed -rn "s/^$1=('|\"|)(.*)\1/\2/ip" "$CONF" | tail -n 1) 

, и вы должны быть хорошими.

Что касается (...) выпуск, использование \( и \). Это переносная нотация.

+1

Цитаты вне' $() 'в порядке, если это не нужно.' \ ('И' \) 'не являются переносимой нотацией, а базовым синтаксисом regex. OP использует расширенный синтаксис regex (см. переключатель' -r'), в котором '\ (' означает литерал '(' в отличие от группы захвата. – Wintermute

+0

Кавычки за пределами $() необходимо удалить. Это то, что вызывает его ошибку RE, потому что первая цитата сопоставляется с одной из неопределенных кавычек в выражении. –

+1

@DannyDaglas Цитаты из-под подоболочки не видны внутри него. Нет ничего плохого в цитировании – 123

Смежные вопросы