我正在学习 Bash 编程,我找到了这个例子,但我不明白它的意思:
filtered_files=`echo "$files" | sed -e 's/^\.\///g'`
Run Code Online (Sandbox Code Playgroud)
特别是传递到“-e”之后的参数sed
。
这是一个不好的例子;你不应该遵循它。
s/pattern/replacement/flags
是一个sed
命令,详细描述见man sed
。在本例中,pattern
是一个正则表达式;replacement
是该模式被替换为何时/何地发现的;并flags
描述有关如何进行更换的详细信息。
在这种情况下,s/^\.\///g
分解如下:
s
是sed
正在运行的命令。/
是用于分隔此命令各部分的印记。(任何字符都可以用作印记,而选择使用/
这种表达方式的人是出于慈善目的,而不是考虑他们正在努力做什么)。^\.\/
是要替换的模式。这^
意味着这仅在一开始就取代了任何东西;\.
仅匹配句点,vs .
(这是匹配任何字符的正则表达式);并且\/
仅匹配 a /
(vs /
,它将继续到此 sed 命令的下一部分,成为所选的印记)。g
中的flags
部分表示每行可以发生多次替换。与 结合使用时^
,这没有任何意义,因为每行只能有一个行首;进一步的证据表明写你的例子的人没有想太多。在处理任意文件名时,以下所有内容都是有问题的,因为在标量变量中存储任意文件名通常是有问题的。
仍在使用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)替换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)
...如果采用原来的方法,就会发生这种情况。
归档时间: |
|
查看次数: |
5014 次 |
最近记录: |