【发布时间】:2015-02-09 06:35:31
【问题描述】:
我真的很难写一个 Bourne shell 脚本。基本上,我试图检测一个名为“ref”的变量的三种输入格式:
- ref="refs/head/.*"(即以“refs/head/”开头,我对斜线后面的位感兴趣)
- ref="refs/tags/.*"(即以“refs/tags/”开头,我对斜线后面的位感兴趣)
- 其他所有内容(即忽略不以“refs/head/”或“refs/tags/”开头的所有内容)
例如,
如果 ref="refs/head/master",设置 TAG="master"
如果 ref="refs/tags/0.2.4",设置 TAG="0.2.4"
对于其他所有内容,设置 TAG=""
现在我在 bash shell 中写了一些东西,但我真的很难将它转换为 Bourne (#!/bin/sh):
#!/bin/bash
#
#This works!
#
TAG=""
re='^refs/head/.*' #regex: begins with refs/head/, ends with anything
re2='^refs/tags/.*' #regex: begins with refs/tags/, ends with anything
if [[ $ref =~ $re ]]; then
#do nothing - OK
true #NOP
else
#check if it's a tag update
if [[ $ref =~ $re2 ]]; then
TAG=${$ref##*/} #looks worse that it is: http://stackoverflow.com/questions/3162385/how-to-split-a-string-in-shell-and-get-the-last-field
fi
exit 0
fi
echo $TAG
我花了很长时间才 a) 编写这个程序 b) 找出为什么我的程序会发疯 - 结果我需要 #!/bin/sh 而不是 #!/bin/bash
如何将其转换为 sh?也许其他人对我的正则表达式体操有更优雅的解决方案?
更新:
感谢到目前为止的回答(尤其是@gboffi)。我想我快到了。
我现在只需要知道 $TAG 是来自“refs/head/”、“refs/tags/”还是两者都没有。我试图修改一些答案,但真的很挣扎 sh。我需要离开并从第一原理中了解更多关于 sh 的信息,而不是试图破解它。
更新 2:
所以睡了一夜之后,我在大约 20 分钟内搞定了。这是我的解决方案:
#!/bin/sh
ref="refs/asdf/master"
TAG=""
TAG="${ref#refs/heads/}"
if [ "$ref" != "${ref#refs/heads/}" ]; then
echo "heads"
echo $TAG
else
TAG="${ref#refs/tags/}"
if [ "$ref" != "${ref#refs/tags/}" ]; then
echo "heads"
echo $TAG
else
TAG=""
fi
fi
echo "--->$TAG"
我确信有一个更优雅的解决方案;但我就是没时间!
【问题讨论】:
-
出于好奇,为什么需要将其从 bash 转换为 sh? sh 没有内置的正则表达式支持,所以它基本上需要重写。
-
@JohnKugelman - 此外,为什么不使用 grep、sed 和 awk 等核心 Unix 工具?真的需要纯shell吗?
-
@JohnKugelman 恐怕我在使用
grep、sed和awk时遇到问题。您能否建议我如何在 sh 脚本中使用这些标准工具来获取“/”上拆分的最后一个元素? -
如果您有一个功能齐全的解决方案,请将其从问题中取出并作为答案,然后将答案视为正确答案。