Заменить символ, кроме последних x входов

У меня есть файл с кучей имен хостов, коррелированный с IP-адресами, который выглядит так:

x-cluster-front-1 192.168.1.2 x-cluster-front-2 192.158.1.10 y-cluster-back-1 10.1.11.99 y-cluster-back-2 10.1.157.38 int.test.example.com 59.2.86.3 super.awesome.machine 123.234.15.6 

И я хочу, чтобы это выглядело так:

 x-cluster-front-1 192.168.1.2 x-cluster-front-2 192.158.1.10 y-cluster-back-1 10.1.11.99 y-cluster-back-2 10.1.157.38 int-test-example-com 59.2.86.3 super-awesome-machine 123.234.15.6 

Мой вопрос: как я могу заменить. (точек) из первого столбца с – (строка), чтобы облегчить сортировку по второму столбцу. Я думал использовать sed для замены точек до первого пробела или замены каждой точки, но последние три, но у меня проблемы с пониманием регулярных выражений и sed … я могу выполнять простые замены, но это происходит над моей головой: D.

Это часть большого скрипта, который я писал в bash. Я застрял в этой части …

  • Как заменить символы только на определенных строках?
  • ksh / bash Форматирование файлов через sed по файлу cat | команда sed
  • Редактировать значения в txt-файле с помощью команды sed / awk / grep
  • Заменить слово после значительных строк и пробелов (inline) с помощью sed?
  • Замените конкретный символ, но не если он внутри ()
  • Почему sed не удаляет мои пустые строки?
  • команда sed добавить несколько строк
  • sed - простая замена регулярного выражения, не заменяющая
  • 9 Solutions collect form web for “Заменить символ, кроме последних x входов”

    Вы можете использовать AWK

     awk '{gsub(/-/,".",$1);print}' infile 

    объяснение

    По умолчанию awk разбивает строку по пробелам. Таким образом, первый столбец строки ( $1 в awk -ese) будет тем, который вы хотите выполнить подстановками. Для этого вы можете использовать:

      gsub(regex,replacement,string) 

    для выполнения требуемой замены.

    Обратите внимание, что gsub поддерживается только для gawk и nawk но во многих современных дистрибутивах awk – это программная ссылка на gawk .

    Если вам нужно сделать замены в первом поле, лучше всего использовать решение awk Rahul, но будьте осторожны, это может повлиять на интервал (поля переписываются с одним пробелом между ними).

    Вы можете избежать этого, написав вместо этого:

     perl -pe 's|\S+|$&=~tr/./-/r|e' file 

    Флаг -p означает «читать входной файл по строке и печатать каждую строку после применения сценария, заданного -e ». Затем замените ( s|pattern|replacement| ) на первую последовательность непространственных символов ( \S+ ) совпадающим шаблоном ( $& ) после замены всех . с - . Хитрость заключается в использовании s

    e где оператор e будет оценивать выражение в качестве замены. Таким образом, вы можете иметь одну замену ( tr/./-/ ), применяемую к совпадению ( $& ) предыдущего ( s

    e ).

    Если вам нужно заменить каждый . с - за исключением последних 3 последних, с GNU sed и при условии, что у вас есть команда rev :

     rev file | sed 's/\./-/4g' | rev 

    Sed – не самый простой инструмент для работы – см. Другие ответы на лучшие инструменты, но это можно сделать.

    Заменить . by - только до первого пространства, используйте s в цикле.

     sed -e ' : a # Label "a" for the branching command s/^\([^ .]*\)\./\1-/ # If there is a "." before the first space, replace it by "-" ta # If the s command matched, branch to a ' 

    (Обратите внимание, что некоторые реализации sed не поддерживают комментарии в той же строке. GNU sed делает.)

    Вместо этого выполнить замену до последнего места:

     sed -e ' : a # Label "a" for the branching command s/\.\(.* \)/-\1/ # If there is a "." before the last space, replace it by "-" ta # If the s command matched, branch to a ' 

    Другой метод использует пространство для хранения sed. Сохраните бит, который вы не хотите изменять в пространстве удержания, выполните свою работу, а затем вспомните пространство удержания. Здесь я разделил строку в последнем пространстве и заменил точки пунктиром в первой части.

     sed -e ' h # Save the current line to the hold space s/.* / / # Remove everything up to the last space x # Swap the work space with the hold space s/[^ ]*$// # Remove everything after the last space y/./-/ # Replace all "." by "-" G # Append the content of the hold to the work space s/\n// # Remove the newline introduced by G ' 

    Поскольку Рахул дал вам канонический ответ для вашего случая использования, я подумал, что я бы наткнулся на ответную проблему: заменяя все, кроме последних x появлением регулярного выражения:

     perl -pe ' $count = tr{.}{.}; # Count '.' on the current line $x = 3; next LINE if $count <= $x; while(s{\.}{-}){ # Substitute one '.' with a '-' last if ++$i == $count - $x # Quit the loop before the last x substitutions } $i = 0 ' your_file 

    Вышеприведенный код (проверенный) не предполагает, что у вас есть поля, разделенные пробелами. Он заменит все точки на линии тире, за исключением последних 3 точек. Замените 3 в коде по своему вкусу.

    Для этого вы можете использовать множество различных инструментов. Рахул Патил уже дал вам gawk поэтому вот несколько других:

    • Perl

       perl -lane '$F[0]=~s/\./-/g; print "@F"' file 

      Переключатель -a заставляет perl автоматически разбивать входные строки на пробелы и сохранять полученные поля в массиве @F . Поэтому первое поле будет $F[0] поэтому мы заменим ( s/// ) все вхождения . с - в первом поле, а затем распечатать весь массив.

    • оболочка

        while read -rab; do printf "%s %s\n" "${a//./-}" "$b"; done < file 

      Здесь цикл while считывает файл и автоматически разбивается на whitespace. Это создает два поля: $first и $rest . Конструкция ${first//pattern/replacement} заменяет все вхождения pattern replacement .

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

     while read -r host ip; do echo "$(sed 's/\./-/g' <<< "$host") $ip" done < input_file 

    В зависимости от вашей оболочки вы также можете использовать $ {host //./-} вместо команды sed.

     sed 's/\./-/' <file name> 

    Без использования g в конце команды вы можете это сделать … Это просто заменит 1-е появление шаблона

    Interesting Posts

    построение кода из исходного кода и добавление их к вашему пути

    Найти файл во многих zip-файлах (например, найти команду для каталогов)

    Как сбросить графические драйверы и восстановить значения по умолчанию?

    Какая функция в ядре Linux отключает действие?

    Разница между «man ls» и «ls –help»?

    как предоставить пользовательские имена файлов при выполнении команды split в unix?

    Как считать рекурсивно количество файлов в нескольких каталогах?

    Как отключить клиентскую часть шифрования в Linux при установке доли Azure с помощью mount.cifs с помощью SMBv3?

    Отправляйте мой IP-адрес на удаленный сервер каждый раз при загрузке

    Как экспортировать LD_LIBRARY_PATH всем пользователям и системным службам

    Разгон программного обеспечения для Linux?

    Подключить принтер Windows к машине Linux через samba

    Безопасный способ позволить пользователям загружать свои открытые ключи

    Результат bash compgen содержит цветовые коды терминала

    Разница между Oracle VM и Citrix XEN?

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