Как убрать все.из строки кроме последней? - PullRequest
6 голосов
/ 19 марта 2012

Я хотел бы удалить все . из строки, кроме последней.

Это можно сделать в 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?

Ответы [ 7 ]

9 голосов
/ 19 марта 2012

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

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

Результат:

123.4

РЕДАКТИРОВАНИЕ для добавленияисправить ваше решение, используя 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";
4 голосов
/ 19 марта 2012

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

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

splice принимает аргументы ARRAY или EXPR, OFFSET, LENGTH, 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.

4 голосов
/ 19 марта 2012

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

3 голосов
/ 19 марта 2012

при сомнениях 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

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

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

по электронной почте Ой. $ # 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 голос
/ 19 марта 2012

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

my @parts = split /\./, $s;
$s = join('', splice(@parts, 0, -1)) . '.' . $parts[-1];
0 голосов
/ 19 марта 2012

Первый аргумент split - это регулярное выражение.В регулярных выражениях «.» означает «соответствовать любому символу» (с / с) или «соответствовать любому символу, кроме 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;
0 голосов
/ 19 марта 2012

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

use strict;
use warnings;

my $s = '1.2.3.4';

my @parts = split /\./, $s;
splice @parts, -1, 0, '.';
$s = join "", @parts;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...