2012-03-20 2 views
1

У меня есть файл, который я пытаюсь изменить с помощью Perl с терминала в Ubuntu Linux (Natty).Странное поведение с командной строкой perl

Имя файла vm.args и первые две строки следующим образом:

## Name of the riak node 
-name [email protected] 

Я пытаюсь использовать Perl для обновления адреса IP. Ниже мой код:

riak_ip=`ifconfig eth1 | grep "inet addr" | cut -d ":" -f2 | cut -d " " -f1` 
perl -0777 -i -pe "s/(\-name[\t ]*riak\@)[^\n]+/\1$riak_ip/g" vm.args 

Предположим, что адрес ip, который я получаю, является 10.181.106.32. Команда perl дает мне результат, который я не могу понять. В результате первые две строки в моем файле после того, как я запускаю выше в терминале стать:

## Name of the riak node 
H.181.106.32 

Какая это буква H и часть адреса IP.

Я не могу понять, что я делаю неправильно, и буду признателен за помощь.

Заранее благодарен.

+0

Это Unix, не так ли? Вы получите лучшие результаты, если вы ставите аргумент '-e' perl' в одинарные кавычки вместо двойных кавычек. – mob

+0

@mob - за исключением того, что он хочет, чтобы env var '$ riak_ip' расширялся в встроенный скрипт perl. –

+1

'\ 1' - это шаблон регулярного выражения, соответствующий строке, захваченной первым захватом. Нет смысла использовать его в замещающем выражении. Это также является причиной ваших проблем. Избавиться от этого! Вы должны использовать '$ 1'. – ikegami

ответ

2

Это, кажется, надежно работает:

perl -0777 -i -pe "s/(-name\\s*[email protected]).*/\${1}$riak_ip/g" vm.args 

"\\1$riak_ip ", кажется, вызывает некоторые проблемы, поскольку perl видел его как" \1172.20.2.136 ", если $riak_ip был 172.20.2.136. Я предполагаю, что обратная ссылка на «1172» вызывала некоторые странности. В любом случае, переход на форму ${1} исключает возможность неправильного толкования (каламбур).

+1

'\ 117' - это символ 0117, который является символом 0x4F, который является символом 79, который является« O », который является ʟᴀᴛɪɴ ᴄᴀᴘɪᴛᴀʟ ʟᴇᴛᴛᴇʀ ᴏ. – tchrist

+0

@ D.Shawley Большое спасибо, это сделал трюк. Я также обращу внимание на форму '$ {1}', которую вы упомянули, я думаю, что я буду использовать ее с этого момента. Приветствия. –

+0

@tchrist Я думаю, это объясняет, почему я получил письмо H в своем собственном результате. Спасибо что подметил это. –

-1

Это было бы правильно регулярное выражение:

perl -0777 -i -pe "s/(-name\s*[email protected])\S+/$1$riak_ip/g" vm.args 

Результат:

## Name of the riak node 
10.181.106.32 

Использование \s для космических символов и \S (без пробела), чтобы соответствовать весь IP-адрес. В заменяющей строке вместо этого используется $1\1. - и @ не являются особыми, поэтому их не нужно избегать, хотя с ними нет ничего плохого.

+1

Это неправильно. Ваши $ 1 интерпретируются оболочкой, прежде чем perl получит ее. OP хочет заменить только IP-адрес, сохранив перед ним часть. –

0

Проблема заключается в том, что \1 соединяется с первым октетом IP. Чтобы заставить его работать, несмотря на конкатенацию, необходимо использовать синтаксис ${1} и правильно процитировать. Это работает:

perl -0777 -i -pe "s/(\-name[\t ]*riak\@)[^\n]+/\${1}$riak_ip/g" vm.args 

Вы могли бы рассмотреть, чтобы использовать одинарные кавычки для регулярных выражений частей, чтобы удалить один слой процитировать:

perl -0777 -i -pe 's/(-name[\t ]*[email protected])[^\n]+/${1}'"$riak_ip"'/g' vm.args 

(ред/исправлено в соответствии с замечаниями, мое предыдущее предложение было неправильно.)

+0

Escaping '\ 1' ничего не решает, поскольку проблема заключается в том, что вместо этого следует использовать' $ 1'. – jwodder

+0

'\ 1' является традиционным/устаревшим синтаксисом для' $ 1'. Они эквивалентны, учитывая, что perl фактически видит один из них. –

+1

@jwodder - это странно ... согласно perl docs и многолетнему соглашению, '\ 1' вполне приемлемо - _" Абсолютные нумерованные группы были упомянуты с использованием \ 1, \ 2 и т. Д., И это обозначение все равно принимается (и, вероятно, всегда будет) »_ –

1

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

perl -0777 -i -pe '($ip)=`ifconfig eth1`=~/inet addr:([\d.]+)/;s/-name\[email protected]\K[\d.]+/$ip/g;' vm.args 

Я был бы признателен, если кто-нибудь подтвердит, работает ли это нормально.Помните, что конструкция \K в Perl-регулярных выражениях является недавним дополнением и может не быть в какой-либо конкретной установке Perl.

0

Звучит неплохо для последовательности \K (v5.10). И [^\n] на самом деле ., если не используется модификатор /s. Нет необходимости в опции /g, если вы не собираетесь менять строку несколько раз.

perl -0777 -i -pe "s/\-name[\t ]*riak\@\K.+/$riak_ip/" vm.args 
Смежные вопросы