2012-06-12 32 views
4

Perl重命名實用程序在日常文件工作中做得非常好,尤其是在我不時檢查MP3收藏的時候。如何在Perl中將部分子字符串更改爲混合大小寫

有些人有資本總是藝術家名稱可怕的習慣,這樣

03 - ARTIST NAME - Song Title.mp3 

我想這將重命名爲一個更從容的前瞻性混合的情況下,這樣的

03 - Artist Name - Song Title.mp3 

但是,它也應該以智能的方式完成。

有可能是法國或意大利的遊戲,例如:

05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3 

07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3 

,因此,我做希望這些只得到了改變大小寫混合-後,藝術家部分。

一種方法,沒有工作,是

rename 's/(\d{1,2} -)([A-Z ]+)([\s\S]+)/$1lc($2)$3/' filename 

我張貼也無妨,因爲它總是給你一個更好的線索,我想要做的事。

我也嘗試用臨時變量替換$2(因爲我不允許更改$ 2,因爲它是隻讀的)並在打印結果之前執行lc(),但是我沒有成功。無論如何,我都是Perl初學者。

+0

所以你想改變第一對連字符之間的一切,以混合大小寫? – Borodin

回答

3

我知道這樣做的最清晰的方法是進行兩階段評估(使用/e修飾符)替換。

在下面的代碼中,外部替換選擇包含邊界連字符的藝術家名稱並替換它。

內一個需要$1 - 藝術家的名字 - 並替換有相同的字符串第一個是小寫字母,與lc,然後用ucfirst資本的非空格字符每個子序列。

按照規定,程序將打印前後名稱。從重命名行刪除#進行重命名。

use strict; 
use warnings; 

my @data = (
    '05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3', 
    '07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3', 
); 

for my $file (@data) { 

    (my $new = $file) =~ s{(-[^-]+-)}{ 
    (my $artist = $1) =~ s/(\S+)/ucfirst lc $1/eg; 
    $artist; 
    }e; 

    print "$file\n"; 
    print "$new\n"; 
    print "\n"; 
    # rename $file, $new; 
} 

輸出

05 - JEAN BAGUETTE - Honi soit qui mal y pense.mp3 
05 - Jean Baguette - Honi soit qui mal y pense.mp3 

07 - SIGNORE AL FORNO - Pazzi sono tutti i calciatori.mp3 
07 - Signore Al Forno - Pazzi sono tutti i calciatori.mp3 

更新

你可能會喜歡的另一種方式是在連字符分割的文件名,編輯,第二部分和他們一起回一起。

來自上述主迴路成爲

for my $file (@data) { 

    my @file = split /-/, $file; 
    $file[1] =~ s/(\S+)/ucfirst lc $1/eg; 
    my $new = join '-', @file; 

    print "$file\n"; 
    print "$new\n"; 
    print "\n"; 
    # rename $file, $new; 
} 

和功能,並輸出保持不變。


更新2

我只試驗了使用/-.*?-/然後使用SUBSTR($ _,$ - [0], $ + [0])作爲一個左值=〜///但遺憾的是它沒有工作

這似乎是這樣一個整潔的想法,我不得不嘗試它。

您撥打substr錯誤,因爲$-[0]$+[0]是字符串中的偏移量。到substr第三個參數必須是一個字符串長度所以你需要寫substr($_, $-[0], $+[0] - $-[0])

此代碼工作正常,並再次產生相同的結果之前

for my $file (@data) { 

    next unless $file =~ /-[^-]+-/; 
    my $new = $file; 
    substr($new, $-[0], $+[0]-$-[0]) =~ s/(\S+)/ucfirst lc $1/eg; 

    print "$file\n"; 
    print "$new\n"; 
    print "\n"; 
    # rename $file, $new; 
} 
+0

是的,這可能是最好的方法。我剛剛嘗試過使用'/-.*?-/'然後使用'substr($ _,$ - [0],$ + [0])'作爲'=〜s ///'的左值',但不幸的是它沒有工作。 – ephemient

+0

@ephemient:謝謝你的一個好主意!我已經更新了我的答案,它正常工作。 Perl的新成語。 – Borodin

+1

右邊有'\ u'和'\ L'時不需要'/ e'。 – tchrist

2

可以使用轉義序列ucfirst在您正則表達式(\u)和lc\L),具有前瞻斷言相結合,需要一個破折號遠一點:

perl -pe 's/(\w)(\w+)(?=.*-)/\u$1\L$2/g' 

如果您想更加正確,可以使用\pL(字母)而不是\w。我認爲這將適用於rename工具。

ETA:更新爲使用\u而不是\U

+0

你想要'\ u'爲第一個,而不是'\ U'。 – tchrist

+0

@tchrist實際上,因爲'$ 1'只是一個字母,所以並不重要。但是我想它可以簡化爲's((w)+())。 – TLP

+2

不,這是不正確的。對於所有可能的代碼點,大寫和標題都不是*相同的情況圖。同樣,它首先映射到lc然後映射到tc或uc實際上是不正確的。你必須寫'\ u $ 1 \ L $ 2',而不是'\ u \ L $ 2'。是的,只有六個代碼點是重要的:U + 0130,U + 03F4,U + 1E9E,U + 2126,U + 212A和U + 212B。 – tchrist

相關問題