Хотите заменить только первое вхождение с sed

Исходный файл

claudio antonio claudio michele 

Я хочу изменить только первое появление «claudio» с «claudia», поэтому результат файла

 claudia antonio claudio michele 

я пытался

 sed -e '1,/claudio/s/claudio/claudia/' nomi 

Но выполняйте глобальную замену. Почему?

  • Что не так с экранированной новой строкой в ​​этой команде sed?
  • sed - почему это не работает?
  • Изменить строку в sed?
  • sed: -e выражение # 1, char 44: команда unterminated 's
  • Как заменить все, кроме определенного шаблона с sed?
  • Заменить последние символы в каждой строке
  • что означает: g означает это действие?
  • sed, получив ошибку: sed -e выражение # 1, команда char 28: unterminated `s '
  • 7 Solutions collect form web for “Хотите заменить только первое вхождение с sed”

    Если вы используете GNU sed , попробуйте:

     sed -e '0,/claudio/ s/claudio/claudia/' nomi 

    sed не запускает проверку для регулярного выражения, которое заканчивает диапазон, до тех пор, пока строка, начинающая этот диапазон.

    От man sed (POSIX manpage, акцент мой):

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

    Использование awk

    Диапазоны в awk работают больше, как вы ожидали:

     $ awk 'NR==1,/claudio/{sub(/claudio/, "claudia")} 1' nomi claudia antonio claudio michele 

    Объяснение:

    • NR==1,/claudio/

      Это диапазон, который начинается с строки 1 и заканчивается первым вступлением claudio .

    • sub(/claudio/, "claudia")

      Пока мы находимся в диапазоне, эта команда подстановки выполняется.

    • 1

      Это критическая стенограмма awk для печати строки.

    Вот еще 2 дополнительных усилия с sed: они оба читают весь файл в одну строку, затем поиск заменяет только первый.

     sed -n ':a;N;$bb;ba;:b;s/\(claudi\)o/\1a/;p' file sed -n '1h;1!H;${g;s/\(claudi\)o/\1a/;p;}' file 

    С комментарием:

     sed -n ' # don't implicitly print input :a # label "a" N # append next line to pattern space $bb # at the last line, goto "b" ba # goto "a" :b # label "b" s/\(claudi\)o/\1a/ # replace p # and print ' file 
     sed -n ' # don't implicitly print input 1h # put line 1 in the hold space 1!H # for subsequent lines, append to hold space ${ # on the last line g # put the hold space in pattern space s/\(claudi\)o/\1a/ # replace p # print } ' file 

    Вы можете использовать awk с флагом, чтобы узнать, была ли замена уже выполнена. Если нет, продолжайте:

     $ awk '!f && /claudio/ {$0="claudia"; f=1}1' file claudia antonio claudio michele 

    На самом деле это очень просто, если вы просто установите небольшую задержку – нет необходимости идти на недостоверные расширения:

     sed '$H;x;1,/claudio/s/claudio/claudia/;1d' <<\IN claudio antonio claudio michele IN 

    Это просто переводит первую строку на вторую, а вторую на третью и т. Д.

    Он печатает:

     claudia antonio claudio michele 

    И еще один вариант

     sed --in-place=*.bak -e "1 h;1! H;\$! d;$ {g;s/claudio/claudia/;}" -- nomi 

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

     export chngFrom=claudio export chngTo=claudia sed --in-place=*.bak -e "1 h;1! H;\$! d;$ {g;s/${chngFrom}/${chngTo}/;}" -- nomi 

    Это также можно сделать без пространства удержания и без учета всех строк в пространстве шаблонов:

     sed -n '/claudio/{s/o/a/;bx};p;b;:x;p;n;bx' nomi 

    Объяснение: Мы пытаемся найти «claudio», и если мы это сделаем, мы перейдем к небольшому циклу печати-нагрузки между :x и bx . В противном случае мы печатаем и перезапускаем скрипт со следующей строкой.

     sed -n ' # do not print lines by default /claudio/ { # on lines that match "claudio" do ... s/o/a/ # replace "o" with "a" bx # goto label x } # end of do block p # print the pattern space b # go to the end of the script, continue with next line :x # the label x for goto commands p # print the pattern space n # load the next line in the pattern space (clearing old contents) bx # goto the label x ' nomi 
     sed -n '/claudia/{p;Q}' sed -n ' # don't print input /claudia/ # regex search { # when match is found do p; # print line Q # quit sed, don't print last buffered line { # end do block 
    Interesting Posts

    какую команду я буду использовать, чтобы увидеть все строки из файла, начиная с строки, которую я нашел с помощью grep

    Найти команды с помощью частичного имени

    установить минимальный рабочий стол на CentOS 6.3

    Некоторые ключи (стрелки, прокрутка вверх, вниз) не работают в rdesktop-vrdp

    Включение только синхронного TRIM

    Почему Ubuntu хранит журналы демона на /var/log/daemon.log.1 вместо /var/log/daemon.log?

    ZSH: история поиска по клавишам вверх и вниз?

    Сохранять счет из файла журнала

    Как вы извлекаете целое слово, содержащее подстроку?

    Как я могу сделать блок синтаксического анализа perl более разумным?

    Файл большой зоны для bind9: блокировка рекламы

    сохранить форматирование вывода perldoc

    Ошибка при установке Debian 7 на виртуальной машине (Ошибка при попытке запуска: chroot / target mount -t proc proc / proc)

    Почему существует разница между последними и последними коммандными записями и почему в записи последних записей нет последней записи входа для пользователя?

    Как проверить контрольные суммы в режиме on-line в brtfs?

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