Я начну с оригинальной команды, а не с нуля. Сборка с нуля является отличным подходом в этом случае, тем не менее, существует образовательная ценность в понимании оригинальной команды и шагов, которые вы можете предпринять, чтобы приспособить команду к вашим потребностям.
Суть оригинальной команды:
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
будет строить это решение с нуля. Как вы можете видеть, возможно уменьшить исходную команду, шаг за шагом в логической манере и найти то же решение.