我在 sh 脚本的上下文中看到sed 's=.*/=='
,我很困惑。我在 sed 手册或网络搜索( for sed s=
)中找不到如何s
使用,而不是s///
。除了s
我在这里只看到一个潜在的命令=
(打印当前输入行号)之外,但在这种情况下其余的命令正在做什么......
在 shell 中运行该命令会产生与 eg 的输入相同的输出echo 'jkfdsa=335r34'
,而echo 'jkfdsa=335r34' | sed 's/=.*/==/'
按照手册进行替换。还稍微修改命令为 例如echo 'jkfdsa=3' | sed 's798=.*/==/'
gets
sed: -e expression #1, char 11: unterminated 's' command
,所以原始应该有一些正确的含义。它是什么?
答案1
它们=
是替代分隔符。使用这些是因为模式包含 a /
(这是更常用的分隔符)。几乎任何字符都可以用作替代分隔符,因此s@.*/@@
或s_.*/__
具有相同的含义。使用普通分隔符,sed
表达式可以写为
s/.*\///
(表达式想要匹配的文字/
需要在这里转义)或者,可能更具可读性,
s/.*[/]//
(字符类中的大多数字符[...]
都是文字1)
该sed
表达式的作用是替换任何.*/
不匹配的内容。这将具有删除/
该行中直到并包括最后一个字符的所有内容的效果。它将删除最多最后的 /
(不是第一个)因为.*
对任何字符的任何序列进行贪婪匹配。
例子:
$ echo 'a/b/c' | sed 's/.*[/]//'
c
unterminated 's' command
测试时出现的错误
s798=.*/==/
是由于7
被用作s
命令的分隔符。表达方式
s7.*/77
不过会有效的。
1 ...除了具有特殊含义的字符,[...]
例如^
(在开始时)和-
(当不是第一个、第二个之后^
或最后一个时)。中的字符[
和]
也需要特殊处理[...]
,但这超出了这个问题的范围。
如果这用于获取某个字符串或 shell 变量中路径末尾的文件名,那么该basename
实用程序可能会做得更好(如果路径以斜杠结尾,也会做正确的事情):
$ basename a/b/c
c
$ basename a/b/c/
c
同样,假设变量不包含换行符,标准 shell 参数替换的效果与在命令替换中通过上述表达式${variable##*/}
传递 的值等效,但速度要快很多倍。$variable
sed
变量替换和basename
实用程序还可以正确处理包含换行符的路径名,但这sed
是行不通的(因为它逐行处理输入)。
答案2
从https://backreference.org/2010/02/20/using- Different-delimiters-in-sed/:
sed 可以使用任何字符作为“s”命令的分隔符,这是一个鲜为人知的事实。基本上,sed 将“s”后面的任何内容作为分隔符。
所以中间的斜杠就变成了一个普通的字符。如果我的解释正确的话,你的表达是:
s=.*/==
也可以写成:
s/.*\///
并解释为“删除最后一个斜杠之前的所有内容,包括斜杠”。
答案3
它贪婪地删除之前和/
自身的所有内容。
例子:
echo "nsi/wnx/cmedwcm" | sed 's=.*/=='
输出 :
cmedwcm
这里=
作为 regex(.*/) 和 replacement(无效的)。