2012-03-19 62 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 

編輯使用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 2012-03-19 14:27:04

+1

是否理解你的積極預見的方式是這樣的:首先執行'()'中的內容,並且因爲'。*'是貪婪的,它會找到最後一個'.'和所有'.'正則表達式在途中會被替換爲沒有? – 2012-03-19 14:31:19

+2

@SandraSchlichting不,正則表達式會找到一個文字時期,並且前瞻將斷言在更前面的某個地方至少有一個文字時期。當斷言失敗時,你會發現最後一個時期。 – TLP 2012-03-19 14:35:12

4

首先,逃避拆分指令點:my @parts = split /\./, $s;

4

split使用正則表達式/./,在這種情況下.被認爲是通配符。如果你想拆就字面期間,你需要逃避它:

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

splice需要參數數組或EXPR,OFFSET,長度,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; 

所以基本上,找出你的字符串將有多少個字段被分成,減去一個,然後執行新的分割並設置限制。

+0

第一個不處理'1234',如果它重要,它們都不處理'1.2.3.4.'。 – ikegami 2012-03-19 20:01:52

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 

要使用負偏移我懷疑,我想你想使用偏移陣列減去一(也被稱爲最後一個索引)的0和大小

$ 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 2012-03-19 19:58:36

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 2012-03-19 19:58:51

0

split的第一個參數是一個正則表達式。在正則表達式中,「.」表示「匹配任何字符」(帶/ s)或「匹配除LF以外的任何字符」(不帶/ s)。您需要將其轉義以匹配文字「.」。

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;