Сопоставить параметр в файле и заменить только значение после символа равенства

Я решаю проблему. В моем конфигурационном файле NetworkManager я заменяю строку:

[ключевой файл] неуправляемые -устройства=интерфейс -имя :ap0;интерфейс -имя :wlp3s0;

по:

[ключевой файл] неуправляемые -устройства=интерфейс -имя :ap0;

Я использую скрипт для создания Wi-Fi, я думаю, что это было причиной модификации в моем NetworkManager.conf

0
16.12.2019, 14:21
1 ответ
VAR=anything
escaped_VAR=$(
  printf '%s\n' "$VAR" |
    LC_ALL=C sed 's|[/&\\]|\\&|g;$!s/$/\\/'
)

LC_ALL=C sed -E -i -e "s/^(hostname=).*/\1$escaped_VAR/" -- "$the_file"

Для FreeBSD/macOS sedзамените -iна -i ''.

Как для GNU (, так и для NetBSD/OpenBSD, которые в итоге скопировали GNU вместо FreeBSD )и FreeBSD sed, -iпринимает аргумент, который является именем расширения резервной копии. В GNU sedэтот аргумент является необязательным и должен быть привязан к опции -i, тогда как для FreeBSD sedон обязателен (, но передача пустого аргумента также отключает сохранение резервной копии ).

-ireинтерпретируется как -iс reв качестве аргумента как с GNU, так и с FreeBSD. -i -eинтерпретируется как -iс аргументом -eс FreeBSD, в то время как он интерпретируется как -iбез аргумента, за которым следует опция -eс GNU sed.

Другие примечания:

  • GNU использовался -rдля ERE, использовались BSD -E. -Eнамного лучше, и большинство реализаций остановились на нем, включая GNU sed. Это тот, который будет указан POSIX. Здесь ЭРЭ все равно не нужны. Единственное отличие ERE от BRE — это|(чередование ), остальное — просто синтаксические различия¹. sed -i "s/^\(hostname=\).*/\1$escaped_VAR/"будет работать точно так же.
  • .*может не совпадать до конца строки, если входные данные содержат последовательность байтов, не образующих допустимых символов в локалях, отличных от C(, поэтомуLC_ALL=C).
  • расширение $VARasis в коде, переданном в sed, будет равносильно уязвимости внедрения команд, если содержимое не будет очищено, а &, \, /и экранирование новой строки. Использование \$VAR, как вы, просто заменит литерал $VAR, а не содержимое переменной оболочки $VAR.
  • выполнение s/(hostname=)[^=]*$/$escaped_VAR/заменит строку hostnameтолько в том случае, если значение (или что-то еще справа от hostname=, которое также может быть комментарием, например, )не содержит =. Я не думаю, что это было задумано.
  • без ^, это будет соответствовать hostname=в любом месте файла. ^гарантирует, что это делается только для экземпляров hostname=, которые находятся в начале строки. Если вы хотите разрешить начальные пробелы, вы всегда можете использовать"/^([[:space:]]*hostname...

¹ В POSIX ERE также отсутствует функция обратной ссылки -BRE, хотя большинство реализаций ERE теперь поддерживают их как расширение

1
28.01.2020, 02:38

Теги

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