[1]
не является (т.е. не обязательно) литералом в оболочке. Тогда это не (то есть, конечно, нет) буквально как часть шаблона регулярного выражения в sed
.
Я проверил ваши предыдущие вопросы, и я думаю, что вы используете Bash. Первая часть моего ответа относится ко многим распространенным оболочкам, включая Bash (заметное исключение - zsh).
Возможная проблема в оболочке
Сначала вы назначаете значения переменным:
n=1
field="foo[$n]"
value="2"
Все это работает так, как вы ожидаете. 1
кавычек не является особенным, его не нужно заключать в кавычки. Цитируемые 2
могут или не могут быть указаны, и это не будет иметь никакого значения. Двойные кавычки вокруг foo[$n]
имеют значение; хорошо, что они есть, таким образом [
и ]
ничего особенного, и содержимое переменной field
буквально foo[1]
точно.
Но тогда у вас есть
func_update_value $field $value
где $field
не указано. Сразу после расширения параметра строка
func_update_value foo[1] 2
и затем начинается сопоставление с объектами в вашем текущем каталоге (globbing), особенно:
[…]
Соответствует любому из вложенных символов.
Это означает, что если у вас есть файл или каталог с именем foo1
, строка будет иметь
func_update_value foo1 2
Было бы еще хуже, если бы вы установили n=125
и в каталоге были foo1
и foo5
(и / или foo2
). Более одного файла будет соответствовать шаблону foo[125]
, и окончательная форма строки будет выглядеть так:
func_update_value foo1 foo5 2
что, безусловно, не то, что вы хотите. Вероятно , в текущем каталоге нет ничего с именем foo1
, поэтому шаблон остается буквальным в этой точке и в строке
func_update_value foo[1] 2
запускает функцию func_update_value
с буквальными аргументами foo[1]
и 2
.
Если ваш код не сработает на этом этапе, это только из-за отсутствия foo1
в каталоге, а не из-за правильного кодирования. Правильное кодирование включает двойные кавычки всех переменных. Есть несколько редких сценариев, в которых вы не хотите цитировать, если знаете, что делаете ; Это не один из них.
Также обратите внимание, что в самой функции есть field=$1
где $1
не заключен в кавычки. Проблема с $1
без кавычек такая же, как и с $field
кавычек ранее.
Проблема в sed
Давайте предположим, что ваша функция правильно получила буквальный аргумент foo[1]
а ее локальная переменная field
теперь содержит буквенную строку foo[1]
как и должно быть.
Проблема в том, что [1]
часть регулярного выражения в sed
не является буквальной. Как и в оболочке, он соответствует любому из вложенных символов (за исключением того, что сопоставляется с текстом, а не с именами файлов). foo[125]
будет соответствовать foo1
или foo2
или foo5
. foo[1]
соответствует только foo1
.
Чтобы sed
соответствовал буквально [
и ]
, вам нужно избегать их в шаблоне. Вместо field="foo[$n]"
вам нужно
field="foo\[$n\]"
Можно ли использовать одну команду sed
для обоих случаев?
Да. Ваша текущая команда похожа на sed "s/^\($field=\).*/\1$newvalue/"
и она будет работать до тех пор, пока вы помните, что значение $field
будет интерпретироваться как часть шаблон (поэтому [
, .
, \(
, $
и т. д. являются специальными), а значение $newvalue
будет интерпретироваться как часть замены (например, \1
является специальным). И есть разделитель, который вы выбрали (/
), который не должен встречаться ни в одной из двух переменных, иначе он сломает или изменит синтаксис.
Конечная нота
Одно только второе исправление (добавление обратной косой черты перед [
и ]
) даже предотвратит расширение оболочки […]
, поэтому оно случайно "исправит" проблему цитирования в данном конкретном случае для этого конкретного значения переменной.
В целом, хотя вы должны применить оба исправления. И вам непременно следует привыкнуть к цитированию переменных по умолчанию, это сэкономит ваше время и разочарование при отладке ваших будущих сценариев оболочки. Вот почему мой ответ не ограничивается вторым исправлением.