Я начну с оригинальной команды, а не с нуля. Сборка с нуля является отличным подходом в этом случае, тем не менее, существует образовательная ценность в понимании оригинальной команды и шагов, которые вы можете предпринять, чтобы приспособить команду к вашим потребностям.
Суть оригинальной команды:
sed -e 's/\(+\).*\(@\)/\1\2/'
Выражение имеет форму s/pattern/replacement/ replace /, что означает «искать pattern и заменять его replacement ». / является разделителем здесь.
Ваш pattern \(+\).*\(@\) . Его функция сопоставления была бы такой же, если бы она была +.*@ (Включение чего-либо в \( \) уместно в контексте replacement , мы доберемся до него). Шаблон +.*@ Означает «литерал + за которым следует (почти) любой символ ( .), Повторенный ноль или более раз ( *), за которым следует литерал @ ».
Примечание + соответствует первому возможному + а * является жадным, поэтому это совпадение распространяется от первого + до последнего @ . Это может не иметь значения в вашем конкретном случае, но иногда это очень важно.
Ваша замена \1\2 . Это означает, что «то, что было найдено 1-м \( \) за которым следует то, что было сопоставлено 2-м \( \) ». Ваш первый \( \) на самом деле \(+\) , он соответствует + вы хотите избавиться.
Чтобы прояснить: причина, по которой эти \( \) группы появляются в шаблоне (поэтому шаблон не просто +.*@) Состоит в том, что они определяют фрагменты, упоминаемые как \1 и \2 позже.
Так что, если вы не хотите, чтобы + печатался, минимальное изменение вашей исходной команды будет состоять в том, чтобы пропустить \1 , потому что это именно та часть, которая печатает + в вашем случае.
sed -e 's/\(+\).*\(@\)/\2/'
Но тогда вам не нужно \( \) вокруг + в шаблоне, поэтому вы можете упростить:
sed -e 's/+.*\(@\)/\1/'
Примечание \2 стало \1 потому что \(@\) теперь является 1-й \( \) группой. Кроме того, поскольку он может соответствовать только @ , вы можете использовать литерал @ вместо \1:
sed -e 's/+.*\(@\)/@/'
Но теперь вам не нужно \( \) вообще. Команда становится:
sed -e 's/+.*@/@/'
Тогда вы вспомните, что * жадный, поэтому .* может включать (дополнительно) + или / и @ . Предположим, вы этого не хотите. Вам нужно включить . во что-то, что соответствует чему-либо, кроме @ или +:
sed -e 's/+[^@+]*@/@/'
Это именно то, что дал вам другой ответ . Несколько опытных пользователей sed будет строить это решение с нуля. Как вы можете видеть, возможно уменьшить исходную команду, шаг за шагом в логической манере и найти то же решение.