2012-11-11 43 views
2

請看看我的大腦斷路器。regexp貪心:收縮長路徑

我會停留在與正則表達式萎縮一些長的路徑,像這樣:

/12345/123456/1234/123/12/1/1234567/13245678/123456789/1234567890 

我想這條道路轉換爲以下形式:

/123/123/123/123/12/1/123/123/123/123 

每個「目錄」在路徑中縮寫爲只有3個第一個字符

LONG_PATH="/12345/123456/1234/123/12/1/1234567/13245678/123456789/1234567890" 
perl -pe "s#/(.{1,3})[^/]*?(/|$)#/\1\2#g" <<<$LONG_PATH 

/123/123456/123/123/12 // 1234567/132/123456789/123

sed -E "s#/(.{1,3})[^/]*?(/|$)#/\1\2#g" <<<$LONG_PATH 

/123 /123分之123456/12分之123//132分之1234567/123分之123456789

我曾嘗試也:

perl -pe "s,/(.)(.)?(.)?[^/]*+,/\1\2\3,g" <<<$LONG_PATH 
/123/123/123/123/12//123/132/123/123 

和許多另一個,沒有 「運氣」 - 我仍然不知道。

請給我一個正確的成功之路。

+0

是否要縮短這兩個目錄和文件?如果只有前者使用:'sed -r':a; s |(/ [^ /] {3})[^ /] +/| \ 1/| g; ta'文件' – potong

回答

7

最多匹配三個非斜槓字符並將其捕獲。然後匹配其餘的直到下一個斜槓。通過捕捉替換:

"s#(/[^/]{3})[^/]*#\1#g" 

沒有必要ungreediness或任何東西在這裏,因爲否定的字符類是與/$相互排斥。

編輯:雖然你似乎知道這個我也許應該澄清未來的訪客,這將有兩種perl -pe...sed -E...工作,因爲你已經在你的問題中使用它。正則表達式也可以按照sed -r...的原樣使用。如果你離開了-E-r選項,然後(像往常一樣),你將需要避免兩個括號和大括號:

sed "s#\(/[^/]\{3\}\)[^/]*#\1#g" filename 

還要注意的是池上指出,在Perl中你倒是應該在使用$1替換爲\1

+0

你已經打破了我的謎題。非常感謝。 – sarvavijJana

+0

我得到這個'sed:-e表達式#1,字符24:無效的參考\ 1在's'命令的RHS'上有'GNU sed version 4.2.1' –

+0

@ shiplu.mokadd.im版本:'sed -E「s#(/ [^ /] {1,3})[^ /] *#\ 1#g」filename' –

3

你可以做這樣的:

perl -pe's#[^/]{3}\K[^/]*##g' 
/12345/123456/1234/123/12/1/1234567/13245678/123456789/1234567890 
/123/123/123/123/12/1/123/132/123/123 

查找3個非斜線,並保持(\K)他們,最多刪除以下字符,直到下一個斜線。

正如ikegami指出的,不需要少於三個字符,在這種情況下,可以使用後向斷言而不是\K。好處是\K需要perl v5.10,並且我認爲環視斷言早於此。

perl -pe 's#(?<=[^/]{3})[^/]*##g' 
+0

Perl正則表達式對我來說仍然有黑暗的角落,那很好。感謝這個有趣的例子。 – sarvavijJana

+0

@sarvavijJana不客氣。 – TLP

+1

@ikegami有趣的編輯..如果使用了這個,'\ K'可以交換一個後顧之外,perl版本依賴性略有下降。 – TLP

0

最好的方法似乎是使用File::Spec模塊來拆分和重新組合路徑。撥打map的中間呼叫會將每個路徑段縮小爲前三個字符。此程序演示

use strict; 
use warnings; 

use File::Spec; 

my $path = '/12345/123456/1234/123/12/1/1234567/13245678/123456789/1234567890'; 

my $newpath = File::Spec->catdir(map substr($_, 0, 3), File::Spec->splitdir($path)); 

print $newpath; 

輸出

/123/123/123/123/12/1/123/132/123/123