理解 sed 表达式 's/^\.\///g'

mar*_*zzu 1 linux sed

我正在学习 Bash 编程,我找到了这个例子,但我不明白它的意思:

filtered_files=`echo "$files" | sed -e 's/^\.\///g'`
Run Code Online (Sandbox Code Playgroud)

特别是传递到“-e”之后的参数sed

Cha*_*ffy 5

这是一个不好的例子;你不应该遵循它。


首先,了解手头的 sed 表达式。

s/pattern/replacement/flags是一个sed命令,详细描述见man sed。在本例中,pattern是一个正则表达式;replacement是该模式被替换为何时/何地发现的;并flags描述有关如何进行更换的详细信息。

在这种情况下,s/^\.\///g分解如下:

  • ssed正在运行的命令。
  • /是用于分隔此命令各部分的印记。(任何字符都可以用作印记,而选择使用/这种表达方式的人是出于慈善目的,而不是考虑他们正在努力做什么)。
  • ^\.\/是要替换的模式。这^意味着这仅在一开始就取代了任何东西;\.仅匹配句点,vs .(这是匹配任何字符的正则表达式);并且\/仅匹配 a /(vs /,它将继续到此 sed 命令的下一部分,成为所选的印记)。
  • 下一部分是一个空字符串,这就是为什么以下两个符号之间没有内容的原因。
  • g中的flags部分表示每行可以发生多次替换。与 结合使用时^,这没有任何意义,因为每行只能有一个行首;进一步的证据表明写你的例子的人没有想太多。

使用相同的数据结构,做得更好:

在处理任意文件名时,以下所有内容都是有问题的,因为在标量变量中存储任意文件名通常是有问题的。

  1. 仍在使用sed

    # Use printf instead of echo to avoid bugginess if your "files" string is "-n" or "-e"
    # Use "@" as your sigil to avoid needing to backslash-escape all the "\"s
    filtered_files=$(printf '%s\n' "$files" | sed -e 's@^[.]/@@g'`)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 替换sed为 bash 内置命令:

    # This is much faster than shelling out to any external tool
    filtered_files=${files//.\//}
    
    Run Code Online (Sandbox Code Playgroud)

使用更好的数据结构

而不是跑步

files=$(find .)
Run Code Online (Sandbox Code Playgroud)

...反而:

files=( )
while IFS= read -r -d '' filename; do
  files+=( "$filename" )
done < <(find . -print0)
Run Code Online (Sandbox Code Playgroud)

将文件存储在数组中;它看起来很复杂,但它更安全——即使文件名包含空格、引号字符、换行文字等也能正常工作。

此外,这意味着您可以执行以下操作:

# Remove the leading ./ from each name; don't remove ./ at any other position in a name
filtered_files=( "${files[@]#./}" )
Run Code Online (Sandbox Code Playgroud)

这意味着一个名为

./foo/this directory name (which has spaces) ends with a period./bar
Run Code Online (Sandbox Code Playgroud)

将正确地转换为

foo/this directory name (which has spaces) ends with a period./bar
Run Code Online (Sandbox Code Playgroud)

而不是

foo/this directory name (which has spaces) ends with a periodbar
Run Code Online (Sandbox Code Playgroud)

...如果采用原来的方法,就会发生这种情况。