2012-03-19 2 views
5

Я хочу удалить все . из строки, за исключением последних.Как удалить все. из строки, кроме последней?

Это может быть сделано в JavaScript, как так

var s='1.2.3.4'; 
s=s.split('.'); 
s.splice(s.length-1,0,'.'); 
s.join(''); 

но когда попробовать то же самое в Perl

my @parts = split /./, $s; 
my @a = splice @parts, $#parts-1,0; 
$s = join "", @a; 

я

Modification of non-creatable array value attempted, subscript -2 at ./test.pl line 15. 

Вопрос

Может ли кто-нибудь понять, как это сделать на Perl?

ответ

8

я хотел бы использовать регулярное выражение с положительным заглядывая вперёд в perl для выполнения этой задачи:

perl -pe 's/\.(?=.*\.)//g' <<<"1.2.3.4" 

Результат:

123.4 

EDIT, чтобы добавить исправление к вашему решению с помощью split:

use warnings; 
use strict; 

my $s = '1.2.3.4'; 
my @parts = split /\./, $s; 
$s = join("", @parts[0 .. $#parts-1]) . '.' . $parts[$#parts]; 
printf "$s\n"; 
+2

Чрезмерное использование 'printf' там, когда' print' будет достаточно. – TLP

+1

Является ли способ понять ваш позитивный взгляд вперед следующим образом: контент в '()' выполняется сначала, а потому, что '. *' Жадный, он найдет последние '.' и все' .''s регулярное выражение встречается на своем пути, которое заменяется ничем? –

+2

@SandraSchlichting Нет, регулярное выражение найдет буквальный период, и прогноз будет утверждать, что есть где-то еще один буквальный период. Когда утверждение не удастся, вы найдете последний период. – TLP

4

Прежде всего, избежать точка в разделенной инструкции: my @parts = split /\./, $s;

4

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

... split /\./, $s; 

splice принимает аргументы ARRAY или EXPR, офсет, длина, LIST (Perl v5.14). Если LENGTH равно 0, ничего не удаляется, и поэтому ничего не возвращается.

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

my @parts = split /\./, $s; 
my $end = pop @parts; 
$s  = join "", @parts, ".$end"; 

Или возможно манипулировать раскол

my @parts = split /\./, $s; 
my $limit = @parts - 1; # the field count for split 
$s  = join "", split /\./, $s, $limit; 

Так в основном, узнать, сколько полей ваша строка будет разбита на отнимите один, а затем выполнить новый раскол и установите для него LIMIT.

+0

Первый не обрабатывает '1234', и ни один из них не обрабатывает' 1.2.3.4'', если это имеет значение. – ikegami

3

в случае сомнений, use diagnostics;

$ perl -Mdiagnostics -le " splice @ARGV, -1 ,0 " 
Modification of non-creatable array value attempted, subscript -1 at -e line 1 (#1) 
    (F) You tried to make an array value spring into existence, and the 
    subscript was probably negative, even counting from end of the array 
    backwards. 

Uncaught exception from user code: 
     Modification of non-creatable array value attempted, subscript -1 at -e line 1. 
at -e line 1. 

$ perl -Mdiagnostics -le " splice @ARGV, -1 ,0 " argv now not empty 

Я сомневаюсь, что вы хотите использовать отрицательные сдвиги, я думаю, что вы хотите использовать смещение-и размера массива минус один (также известный как последний индекс)

$ perl -le " print for splice @ARGV, 0, $#ARGV-1 " a b c 
a 

Ooops.$ # ARGV последний индекс, а не $ # ARGV -1, так

$ perl -le " print for splice @ARGV, 0, $#ARGV " a b c 
a 
b 

, но если вы все еще хотите, чтобы некоторые арифметические операции вы можете использовать @ARGV, потому что в скалярном контексте его размер массива

$ perl -le " print for splice @ARGV, 0, @ARGV-1 " a b c 
a 
b 

Боковое преимущество использования неотрицательных смещений со сращиванием? Он не умирает, когда массив пуст

$ perl -le " print for splice @ARGV, 0, 10 " 
1

Это больше похоже на то, что вы пытаетесь сделать в Perl

my @parts = split /\./, $s; 
$s = join('', splice(@parts, 0, -1)) . '.' . $parts[-1]; 
+0

Не обрабатывает '1234' или' 1.2.3.4.', если это имеет значение. – ikegami

0

Вы пропустили '.' от вашего splice вызова. Вот как это должно выглядеть:

use strict; 
use warnings; 

my $s = '1.2.3.4'; 

my @parts = split /\./, $s; 
splice @parts, -1, 0, '.'; 
$s = join "", @parts; 
+0

Не обрабатывает '1234' или' 1.2.3.4.', если это имеет значение. – ikegami

0

Первый аргумент split является регулярным выражением. В регулярных выражениях «.» означает «соответствовать любому символу» (с/s) или «соответствовать любому символу, кроме LF» (без/с). Вам нужно убежать от него, чтобы соответствовать буквальному «.».

my @parts = split(/\./, $s, -1);   # "-1" to handle "1.2.3.4." 
splice(@parts, -1, 0, '.') if @parts > 2; # "if" to handle "1234" 
$s = join('', @parts); 

Замещение может сделать это, а также:

$s =~ s/\.(?=.*\.)//sg;