's=.*/==' 在 sed 中有什么作用?

Ale*_*nov 11 sed

我sed 's=.*/=='在 sh 脚本的上下文中看到了,我很困惑。我在 sed 手册或网络搜索(for sed s=)中找不到如何s使用,而不是s///. 除了s我在这里只看到一个潜在的命令=(打印当前输入行号),但在这种情况下,其余的在做什么......

在 shell 中运行命令会产生与 eg 的输入相同的输出echo 'jkfdsa=335r34',而echo 'jkfdsa=335r34' | sed 's/=.*/==/'根据手册进行替换。也稍微修改 command 为 eg echo 'jkfdsa=3' | sed 's798=.*/==/'given
sed: -e expression #1, char 11: unterminated 's' command,所以 original 应该有一些正确的含义。它是什么?

Kus*_*nda 26

该=是替代分隔符。使用这些是因为模式包含 a /(这是更常用的分隔符)。几乎任何字符都可以用作替代分隔符,因此s@.*/@@或s_.*/__将意味着相同的事情。使用普通分隔符,sed表达式可以写成

s/.*\///
Run Code Online (Sandbox Code Playgroud)

(/表达式想要匹配的文字需要在此处转义)或者,可能更具可读性,

s/.*[/]//
Run Code Online (Sandbox Code Playgroud)

([...]字符类中的大多数字符都是文字1)

该sed表达式的作用是将匹配的任何内容替换.*/为空。这将具有删除所有内容的效果,包括/该行的最后一个字符。它将删除到最后一个 /(不是第一个),因为.*它会贪婪地匹配任何字符的任何序列。

例子:

$ echo 'a/b/c' | sed 's/.*[/]//'
c
Run Code Online (Sandbox Code Playgroud)

unterminated 's' command测试时遇到的错误

s798=.*/==/
Run Code Online (Sandbox Code Playgroud)

是因为7被用作s命令的分隔符。表达方式

s7.*/77
Run Code Online (Sandbox Code Playgroud)

虽然会起作用。


1 ... 除了具有特殊含义的字符,[...]例如^(在开头)和-(当不是第一个、第二个之后^或最后一个时)。内的字符[和]也需要特殊处理[...],但这超出了本问题的范围。


如果这用于获取某个字符串或 shell 变量中路径末尾的文件名,那么该basename实用程序可能会做得更好(如果路径以斜杠结尾,它也会做正确的事情):

$ basename a/b/c
c
$ basename a/b/c/
c
Run Code Online (Sandbox Code Playgroud)

同样,标准 shell 参数替换${variable##*/},假设变量不包含换行符,其效果等同于在命令替换中$variable通过上述sed表达式传递值,但要快很多倍。

变量替换和该basename实用程序还可以正确处理包含换行符的路径名,但这sed是行不通的(因为它会逐行处理其输入)。

  • 是的,现在我看到`在任何给定的 s 命令中,/ 字符可以被任何其他单个字符统一替换。` (2认同)

小智 12

来自https://backreference.org/2010/02/20/using-different-delimiters-in-sed/:

sed 可以使用任何字符作为“s”命令的分隔符,这是一个鲜为人知的事实。基本上,sed 将“s”后面的任何内容作为分隔符。

所以中间的斜线就变成了普通字符。如果我正确解释它,你的表达:

s=.*/==
Run Code Online (Sandbox Code Playgroud)

也可以写成:

s/.*\///
Run Code Online (Sandbox Code Playgroud)

并解释为“删除最后一个斜线之前的任何内容,包括斜线”。


Siv*_*iva 10

它贪婪地删除之前和/本身的所有内容。

例子:

 echo "nsi/wnx/cmedwcm" | sed 's=.*/=='
Run Code Online (Sandbox Code Playgroud)

输出 :

cmedwcm
Run Code Online (Sandbox Code Playgroud)

这里=用作正则表达式(.*/) 和替换( null )的分隔符。