sed: поиск и замена различных столбцов

У меня есть документ, в котором поля разделены двоеточием (:), где мне нужно время от времени менять второе поле. Документ выглядит так:

name1:UhX.PPFW7$YhPMH0BISY:23490::::::
name2:1./0oV$GEs6WJpE$LHXhy:19239:0:29388:2::29302:
...

Второе поле файла будет время от времени изменяться и может содержать пару символов регулярного выражения ($ .) и косую черту.

Я хотел бы заменить только второе поле, так как данные, которые следуют за ним, могут быть другими в будущем. Если я сделаю:

sed -e "s~^name2:.*:~name2:aTest\$repl.ace:~g" tst

Текст справа от второго столбца теряется:

name2:aTest$repl.ace:

(например, «19239:0:29388:2::29302:»). Есть ли способ, которым sed может заменить меняющийся столбец и сохранить остальную часть строки? Или, возможно, есть лучшая программа для этого?


person Todd Partridge 'Gen2ly'    schedule 22.09.2009    source источник


Ответы (3)


Самый простой способ — изменить .* в регулярном выражении так, чтобы оно соответствовало только тому, что действительно может отображаться во втором поле, например:

sed -e "s~^name2:[^:]*:~name2:aTest\$repl.ace:~g" tst

([^:]* == все, что не содержит двоеточия), или:

sed -e "s~^name2:[$./0-9a-zA-Z]*:~name2:aTest\$repl.ace:~g" tst

([blah]* == любое количество перечисленных символов)

person Anthony Towns    schedule 22.09.2009
comment
Эй, это здорово. Было интересно, возможно ли это в sed. Думал, что, возможно, я смотрю на более сложную команду. Спасибо за совет, Энтони. - person Todd Partridge 'Gen2ly'; 22.09.2009

Sed, вероятно, не лучший инструмент для этого, потому что если он действительно не знает о полях. Рассмотрим вместо этого awk (который имеет встроенную концепцию полей):

$ awk -F : 'NF>=2{split($0,a,":");a[2]="new sting";printf(a[1]);for(i=2;i<=NF;i++){printf":%s",a[i]};printf("\n");}' <input file>

или отформатировать для удобочитаемости:

awk -F : 'NF>=2 {
                   split($0,a,":");
                   a[2]="new sting";
                   printf(a[1]);
                   for(i=2;i<=NF;i++){
                     printf":%s",a[i]
                   };
                   printf("\n");
                 }' <input file>

Для общности вы можете заменить ":" на FS. Также стоит обратить внимание на его join функцию, которая сделает реализацию чище, если вы пишете скрипт, а не работаете в командной строке.

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

$2=="string to match"

or

$2~/regex to match/
person dmckee --- ex-moderator kitten    schedule 22.09.2009
comment
хех, awk немного выше моего понимания в то время, но он работает. Спасибо. - person Todd Partridge 'Gen2ly'; 22.09.2009

Попробуй это:

perl -pe 's~^name2:.*?:~name2:aTest\$repl.ace:~g' test
person ennuikiller    schedule 22.09.2009
comment
Начинаю любить perl — все синтаксисы, которые он использует (которые я видел), легко запоминаются. Спасибо за подсказку ennuikiller. - person Todd Partridge 'Gen2ly'; 22.09.2009