используя sed с амперсандом (&)

19

Я использую sed для поиска и замены шаблонов в имеющихся у меня файлах SAS, а не для их индивидуального изменения. Проблема в том, что я пытаюсь заменить макропеременные, и когда я использую амперсанд, он обрабатывается неправильно.

Here's my code:
sed -ie 's/user=&uid./user=&sysuserid./g' *_table_*.sas

всякий раз, когда я запускаю эту команду, она кажется добавляющей и делающей всякие прикольные вещи с оригинальным текстом.

Вопрос: Как заменить текст, содержащий амперсанды, командой sed?

lucasdavis500
источник
6
&это специальный символ, поэтому его нужно экранировать при использовании в RHS - в вашем случае вам нужно бежать, 's/user=&uid./user=\&sysuserid./g'хотя я подозреваю, что вам также нужно экранировать точку в LHS, чтобы соответствовать буквальной точке, так что вам действительно нужно's/user=&uid\./user=\&sysuserid./g'
don_crissti
1
да, «&» справа в основном означает «все, что совпадает слева», поэтому избегайте его с помощью «\». Вы должны сделать это ответ, а не просто комментарий.
Эдвард Фальк
мне не нужно было бежать первый период ... просто любопытно, кому-то еще было любопытно :)
lucasdavis500

Ответы:

25

&является особенным в тексте замены: это означает «всю часть ввода, которая была сопоставлена ​​с шаблоном», поэтому то, что вы здесь делаете, заменяется user=&uidXна user=user=&uidXsysuserid.. Чтобы вставить фактический амперсанд в тексте замены, используйте \&.

Другая вещь, которая выглядит неправильно, заключается в том, что .в шаблоне поиска обозначается любой символ (кроме новой строки), но .в конце заменяющего текста находится буквальная точка. Если вы хотите заменить только буквальную строку user=&uid., защитите .ее обратной косой чертой.

sed -e 's/user=&uid\./user=\&sysuserid./g'

Если вы хотите заменить какой-либо один символ и сохранить его в результате, поместите этот символ в группу и используйте \1в замещении для ссылки на эту группу.

sed -e 's/user=&uid\(.\)/user=\&sysuserid\1/g'

Фактически, учитывая повторение между исходным текстом и заменой, вы все равно должны использовать группы:

sed -e 's/\(user=&\)u\(id\.\)/\1sysuser\2/g'

то есть «заменить uна sysuserмежду user=&и id.».

Жиль "ТАК - прекрати быть злым"
источник
не могли бы вы объяснить группы?
lucasdavis500
2
@ lucasdavis500 Группа идентифицирует часть шаблона. Он ограничен скобками с обратной косой чертой. Например, \(user=&\)шаблон, который сопоставляет user&и сохраняет строку соответствия как группу (группа номер 1, так как это первая группа в шаблоне). Затем в замене \1заменяется строка, хранящаяся для группы № 1.
Жиль "ТАК - перестать быть злым"
Вы имеете в виду (пользователь = &) хранит пользователь = &, а не пользователь &?
lucasdavis500
@ lucasdavis500 Я не понимаю ваш комментарий. Символ =в регулярных выражениях и в замещающем тексте означает сам по себе, так что user=&совпадает только user=&, а user=&в замещающем тексте user=следует часть строки, соответствующая регулярному выражению.
Жиль "ТАК - перестань быть злым"
1
@ lucasdavis500 =Персонаж не имеет особого значения. user=&в тексте замены выдается user=сопровождаемый исходным сопоставленным текстом. user=\&в тексте замены выдаетuser=&
Жиль "ТАК - перестань быть злым"