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

Linux Momonga является японский GNU/дистрибутив Linux, что мощная поддержка функций языка программирования Ruby и его использования сильно защищена. Один проект, который разрабатывается командой Momonga, является библиотекой-оболочкой, которая позволяет пользователю использовать об/мин от Ruby.

9
10.03.2018, 02:47
7 ответов

Можно использовать AWK

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

Объяснение

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

 gsub(regex,replacement,string)

выполнить необходимую замену.

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

7
27.01.2020, 20:04
  • 1
    +1 Beat меня к нему. Я думаю, что объяснение действительно принесло бы пользу автору вопроса и будущим читателям также. –  Joseph R. 28.01.2014, 17:33
  • 2
    @JosephR. Извините я не хорош в объяснении, но я попробовал и обновил.. –  Rahul Patil 28.01.2014, 17:41
  • 3
    Спецификация POSIX для awk на основе nawk, так все современные awk реализации должны иметь gsub. На Солярисе Вам, возможно, понадобится /usr/xpg4/bin/awk или nawk. –  Stéphane Chazelas 28.01.2014, 17:46
  • 4
    @RahulPatil, Если бы Вы не возражаете, я добавил несколько строк, что я думаю, помог бы другим. –  Joseph R. 28.01.2014, 17:47
  • 5
    @JosephR спасибо.., это, кажется прекрасным теперь.. :) –  Rahul Patil 28.01.2014, 17:48

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

Можно избежать его путем записи его вместо этого:

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

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

Если необходимо заменить каждым . с a - кроме последних 3 последних, с GNU sed и принятие Вас имеет a rev команда:

rev file | sed 's/\./-/4g' | rev
6
27.01.2020, 20:04
  • 1
    Обратите внимание, что решение для Perl принимает версию 5.14 или выше (для /r работать). –  Joseph R. 29.01.2014, 01:33

Sed не является самым легким инструментом для задания — видят другие ответы для лучших инструментов — но он может быть сделан.

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

sed -e '
  : a                     # Label "a" for the branching command
  s/^\([^ .]*\)\./\1-/    # If there is a "." before the first space, replace it by "-"
  t a                     # 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 "-"
  t a                     # 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
'
3
27.01.2020, 20:04

Так как Rahul дал Вам канонический ответ для Вашего варианта использования, я думал, что попробую отвечать на номинальную проблему: замена всеми кроме последних x случаев regex:

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 в коде к Вашей симпатии.

2
27.01.2020, 20:04

Можно использовать много различных инструментов для этого. Rahul Patil уже дал Вам a gawk один, таким образом, вот немногие другие:

  • жемчуг

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

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

  • оболочка

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

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

2
27.01.2020, 20:04
  • 1
    +1, В то время как perlrun(1) скажет Вам это -a "режим авторазделения", я предпочитаю думать о нем как"awk режим" :D –  Joseph R. 28.01.2014, 17:50

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

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

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

2
27.01.2020, 20:04
sed 's/\./-/' <file name>

без использования G G В конце команды вы можете сделать это ... Это просто заменит 1-е происхождение шаблона

0
27.01.2020, 20:04

Теги

Похожие вопросы