2015-10-06 50 views
1

我有我希望是一個簡單的問題,這是一個困難的問題。我需要一個安裝文件,名稱類似:試圖從OSX中使用sed中的字符串中刪除版本號

installer_v0.29_linux.run 
installer_v10.22_linux_x64.run 
installer_v1.1_osx.app 
installer_v5.6_windows.exe 

,並與格式

installer_linux.zip 
installer_linux_x64.zip 
installer_osx.zip 
installer_windows.zip 

壓縮它到一個文件我已經在OSX上運行一個bash腳本做幾乎一切我需要在構建鏈,肯定我可以使用的東西,像sed實現這一目標:

ZIP_NAME=`echo "$OUTPUT_NAME" | sed -E 's/_(?:\d*\.)?\d+//g'` 

也就是說,一個空白代替正則表達式_(?:\d*\.)?\d+ - 正則表達式應該匹配任何以下劃線開頭的小數。

但是,當我嘗試運行此操作時,出現錯誤RE error: repetition-operator operand invalid。在這個階段,我很難過 - 我已經Google了谷歌搜索,看不到我做錯了什麼。我寫的正則表達式在Regexr上正常工作,但顯然它的某些元素不被OSX中的sed實現支持。有誰知道我做錯了什麼?

回答

1

你可以試試這個sed

sed 's/_v[^_]*//; s/\.[[:alnum:]]\+$/.zip/' file 
installer_linux.zip 
installer_linux_x64.zip 
installer_osx.zip 
installer_windows.zip 
+0

謝謝,這太棒了!你能否解釋我做錯了什麼以及這個解決方案背後的邏輯?我還沒有見過像[[:alnum:]]之類的令牌。 – stefandz

+1

'[[:alnum:]]'是POSIX類以匹配字母或數字。你的正則表達式匹配一個下劃線後面的數字,而有一個字母'v'。除'\ d'外是'sed'不支持的PCRE類。在sed中,您需要使用'[0-9]'或'[[:digit:]]'作爲'\ d' – anubhava

+1

完美,非常簡潔明瞭的解釋謝謝! – stefandz

0

嘗試這種方式也

sed 's/_[^_]\+//' FileName 

輸出:

installer_linux.run 
installer_linux_x64.run 
installer_osx.app 
installer_windows.exe 

如果你想添加替換zip代替run以下方法使用

sed 's/\([^_]\+\).*\(_.*\).*/\1\2.zip/' Filename 

輸出:

installer_linux.run.zip 
installer_x64.run.zip 
installer_osx.app.zip 
installer_windows.exe.zip 
+0

這對我不起作用 - 我得到了和我一樣的內容。請記住,我在OSX上執行此操作。 – stefandz

+0

你有哪個輸出或錯誤? – Kalanidhi

+0

使用此解決方案,輸出與我的輸入相同。你在使用OSX嗎? – stefandz

1

你不需要sed,只是一些參數擴展魔術延長圖案。

shopt -s extglob 
zip_name=${OUTPUT_NAME/_v+([^_])/} 

模式_v+([^_])開始_v字符串和所有字符直到下一個_匹配。 extglob選項允許使用+(...)模式來匹配一個或多個出現的封閉模式(在本例中爲非_字符)。參數擴展${var/pattern/}刪除$var的擴展中給定模式的第一次出現。

+0

這也是一個很好的選擇 - 你會認爲這比使用'sed'更好嗎?如果是的話,爲什麼? – stefandz

+1

它更高效,因爲您不必啓動運行sed的新進程。不過,它並不便攜,因爲POSIX規範中都沒有提供這些功能。 – chepner