замените символ из строки, которая находится между первым и вторым поиском, используя sed или awk

Мне нужно заменить _ (подчеркивание) на ? (вопросительный знак) в файле, содержащем адреса электронной почты.

Файл выглядит следующим образом:

 EFT_020034-E015133 20140624 /ACC/EMAIL+test_1@mysite.com SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test_123_abc@yoursite.net SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test_456@theirsite.com SHR END 

Ожидаемый результат:

 EFT_020034-E015133 20140624 /ACC/EMAIL+test?1@mysite.com SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test?123?abc@yoursite.net SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test?456@theirsite.com SHR END 

Как это сделать в sed или awk, не влияя на другие символы подчеркивания и только подчеркивание между EMAIL+ (константой) и SHR (константой). Измененный контент должен быть сохранен в новом файле.

  • Как я могу отфильтровать эти «Permission denied» из вывода вывода?
  • переменная sed в запросе?
  • как вставить пробел между отдельными цифрами в файле?
  • Удаление цветовых кодов из вывода
  • Замените в верхнем регистре на нижний регистр, кроме первой буквы каждого слова в определенной строке
  • Присоедините линию рисунка и последовательные непустые строки, разделенные запятыми и заключенные в ()
  • Заменить текст между скобками
  • Регулярные команды и команды с командой sed
  • 3 Solutions collect form web for “замените символ из строки, которая находится между первым и вторым поиском, используя sed или awk”

    awk сделает следующее:

     $ awk '{ gsub("_", "?", $3) ; print }' < data EFT_020034-E015133 20140624 /ACC/EMAIL+test?1@mysite.com SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test?123?abc@yoursite.net SHR END EFT_020034-E015133 20140624 /ACC/EMAIL+test?456@theirsite.com SHR END 

    Адреса электронной почты находятся в поле 3, поэтому мы заменяем _ на ? только в поле 3, в том числе при наличии более одного _ , используя gsub .

    С sed вы могли бы сделать:

     sed -e :1 -e 's/_\([^+]*@\)/?\1/;t1' 

    Это замена _ за которой следует последовательность символов « + за которыми следует @ с ? с последовательностью символов и повторить процесс до тех пор, пока он совпадает.

    Или сделать это только между EMAIL+ и SHR :

     sed -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1' 

    Если вы хотите рассматривать только строки, начинающиеся с ^EFT , вы можете добавить a -e '/^EFT/!b' чтобы оставить в покое те, которые вам не нравятся:

     sed -e '/^EFT/!b' -e :1 -e 's/\(EMAIL+.*\)_\(.*SHR\)/\1?\2/;t1' 

    Обратите внимание, что для ввода типа:

     EFT EMAIL+ foo_bar SHR bar_baz EMAIL+ SHR 

    Оба символа подчеркивания будут заменены, поскольку они оба находятся между EMAIL+ и SHR .

    Чтобы этого избежать, вы можете сделать что-то вроде:

     sed ' /^EFT/!b # leave the non-EFT lines alone (branch out) s/%/%p/g; s/</%l/g; s/>/%r/g; # escape the <>% characters with % s/EMAIL+/</g; s/SHR/>/g; # replace EMAIL+ and SHR with < and > :1 s/\(<[^<>]*\)_\([^<>]*>\)/\1?\2/; t1 s/</EMAIL+/g; s/>/SHR/g; # restore EMAIL+ and SHR s/%r/>/g; s/%l/</g; s/%p/%/g; # restore the escaped <>%' 
     sed '/.*EMAIL+\(.*\)SHR.*/{ h;s//\1/;y/_/?/;G s/\(.*\)\n\(.*EMAIL+\).*SHR/\2\1SHR/}' 

    Это должно сделать работу довольно надежно – она ​​заменит все _ с помощью ? между последним EMAIL+ встречающимся на линии, и последним SHR чтобы происходить на том же и только на тех строках, содержащих обе строки.

    Linux и Unix - лучшая ОС в мире.