![使用bash](https://linux22.com/image/160402/%E4%BD%BF%E7%94%A8bash.png)
我做了一些研究,我可以用“.”分割字符串但我唯一想要替换的是第三个“.”,并且版本号实际上是可变的,那么我该如何进行替换/拆分?
version: 1.8.0.110
但我想要的是这样的输出:
version: 1.8.0-110
答案1
用于sed
例如:
$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110
解释:
sed s/search/replace/x
搜索一个字符串并将其替换为另一个字符串。x
确定要替换的事件 - 这里是第三个。通常g
用于x
表示所有发生的情况。
这里我们希望替换点,但这是正则表达式中该术语所期望的.
特殊字符。因此,我们反斜杠to来指定文字。sed
search
.
\.
.
由于我们在参数中使用特殊字符sed
(此处为反斜杠\
),因此我们需要将整个参数放在单引号中''
。许多人总是在此处使用引号,以免在使用 shell 特有的字符(例如空格)时遇到问题。
答案2
使用bash
您不需要外部程序来执行此操作,特别是因为您似乎想要替换最后的带破折号的句号。 Bash 本身可以处理字符串操作。
假设你有
vers='version: 1.8.0.110'
答案很简单:
$ echo ${vers%.*}-${vers##*.}
1.8.0-110
% 表示删除右侧匹配的最短字符串。 ## 表示删除左侧匹配的最长字符串。
如果超过三个周期怎么办?
如果你真的想替换第三个句点,而不是我上面假设的最后一个句点,那么在 bash 中它会变得有点棘手,但它仍然是可能的。例如,如果vers='version: 1.8.0.110.hut.hut.hut.hike!'
,您可以找到第三个句点之后的所有内容并使用它来截断字符串:
$ end=${vers#*.*.*.}
$ start=${vers%$end}
$ echo ${start%.}-$end
version: 1.8.0-110.hut.hut.hut.hike!
另一种方法:使用 IFS 将字符串拆分为 bash 数组
虽然这对于这个问题来说有点过分了,但有时将字符串拆分为多个组件并将它们加载到数组中是有用的。
IFS=. read -a foo <<<'version: 1.8.0.110.hut.hut.hut.hike!'
您可以迭代数组$foo
并选择何时打印内容。例如,
echo -n $foo
for ((i=1; i<${foo[@]}; i++)); do
[[ i -eq 3 ]] && echo -n - || echo -n .
echo -n ${foo[i]};
done
echo
答案3
在这种情况下,第三个也是最后一个。如果您可以放心地假设您总是需要更改最后一个.
,您可以这样做:
$ echo 'version: 1.8.0.110' | sed 's/\.\([^.]*\)$/-\1/'
version: 1.8.0-110
或者,如果您sed
支持-E
(大多数支持):
$ echo 'version: 1.8.0.110' | sed -E 's/\.([^.]*)$/-\1/'
version: 1.8.0-110
这将查找 a .
,然后查找 0 个或多个非.
字符 ( [^.]
),直到行尾 ( $
)。因为[^.]*
位于括号 ( ) 中,所以它被“捕获”并且可以在替换运算符的右侧\( \)
引用。\1
因此,这将用 a 和那些字符替换其后面的.
和非字符。-.
-
如果这一定是第三次而不是最后一次@Ned64 已经给出了最简单的方法,但作为替代方案,您可以这样做:
$ echo 'version: 1.8.0.110' | perl -pe 's/(([^.]+\.){2}[^.]+)\./$1-/'
version: 1.8.0-110