1

Как удалить весь текст МЕЖДУ двумя символами, используя sed ...

Например:

00arbez+15611@hotmail.com
00aryapan+kee45j@rediffmail.com
asghrsha+hfcdedd@yahoo.com

Я хочу удалить текст + к @ в письме. (Даже знак + необходимо удалить, а символ @ нужно сохранить)

Я использовал следующую команду:

sed -e 's/\(+\).*\(@\)/\1\2/' FILE.txt > RESULT.txt

Но вывод файла включает в себя знак «+». Например: asghrsha+@yahoo.com

Я хочу следующий вывод:

00arbez@hotmail.com
00aryapan@rediffmail.com
asghrsha@yahoo.com

Может кто-нибудь помочь мне с изменением вышеупомянутой команды sed?

2 ответа2

4

Я начну с оригинальной команды, а не с нуля. Сборка с нуля является отличным подходом в этом случае, тем не менее, существует образовательная ценность в понимании оригинальной команды и шагов, которые вы можете предпринять, чтобы приспособить команду к вашим потребностям.

Суть оригинальной команды:

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

3

Простое решение состоит в том, чтобы сопоставить те, которые вы хотите сохранить за границей матча, и поместить их обратно между ними.

sed 's/+[^@+]*@/@/' FILE.txt >RESULT.txt

Вы возвращали вещи, которые не хотели оставлять, что, очевидно, дает неправильный результат.

Вы можете захватить строку, которую хотите сохранить, используя \( ... \) группирующие скобки, но в этом случае, поскольку это полностью статическая строка, я решил сохранить регулярное выражение и строку замены как можно более простым и просто жестким кодом @ в качестве строки замены.

Обратите также внимание на то, как регулярное выражение заботится о том, чтобы не перепрыгивать через несколько плюсов или @ . Может быть, вы действительно хотите использовать любые повторяющиеся символы + ; затем уберите плюс из класса отрицанных символов, оставив только [^@] .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .