2015-10-06 51 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