Другие ответы подходят для примера (файл в формате CSV*(двоеточие -разделенные значения ), искомая строка -будет первым полем, желаемый результат - второе поле ), но ни одно из этих ограничений / условий на самом деле указано в вопросе. И, пока вопрос требует команды который исключает строки, которые начинаются с комментария, это, вероятно, не то, чего на самом деле хочет ОП. (Как насчет строки типа unwanted line:blah:blah #test
, который содержитtest
в комментарии ? )Ответ, который хочет ОП,
grep '^[^#]*test' /etc/oratab
или
grep "^[^#]*$DBNAME" /etc/oratab
, который ищет строку, где появляется test
, и все символы перед ним не являются #
.
Как обычно, ссылки на переменные оболочки всегда должны заключаться в кавычки. (например, "$DB_NAME"
и "$env_var"
), если у вас нет веских причин не делать этого, и вы уверены, что знаете, что делаете. И, , как указывает Стефан Шазела , если $DBNAME
выглядит как не -тривиальное регулярное выражение (например, содержит .
, *
или [
… ]
), возможны нежелательные результаты.
Ваш grep
, вероятно, соответствует более чем одному имени файла, что дает значение в $res
, содержащее новые строки. GNU sed
будет жаловаться точно так же, как вы описываете, при использовании строки замены, которая содержит буквальные символы новой строки.
Не используйте grep
для фильтрации вывода ls
. Если вы хотите, чтобы все имена в текущем каталоге соответствовали шаблону *.pub
, используйте
filenames=( *.pub )
Это создаст массив, содержащий все имена, соответствующие данному шаблону.
Тогда:
sed 's/\(@demo_project_users = \).*/\1'"${filenames[*]%.pub}"'/g' example.conf
Расширение "${filenames[*]%.pub}"
расширится до одной строки, состоящей из имен файлов в массиве filenames
, разделенных пробелами (или любым другим первым символом $IFS
; пробел по умолчанию )и с удаленной строкой суффикса .pub
.
Это бит "${filenames[*]}"
, который расширяется до строки, разделенной пробелом -, а бит %.pub
удаляет суффикс .pub
из каждого имени файла.
Подстановка $res
в команду выполняется оболочкой. Если в значении есть косая черта, sed не может узнать, что это не конечный маркер для команды s
. Точно так же sed интерпретирует любую обратную косую черту или амперсанд в $res
как специальный символ.
Если обратная косая черта и амперсанд не могут появляться в $res
и есть другой символ, который, как вы знаете, также не может появляться, используйте этот символ в качестве разделителя. Например:
sed "s~@demo_project_users =.*~$res~g" example.conf
Также можно заключать специальные символы в кавычки, добавляя перед ними обратную косую черту.
quoted_res=$(printf %s "$res" | sed 's/[\\\/&]/\\&/g')
sed "s/@demo_project_users =.*/$quoted_res/g" example.conf