我正在学习Bash编程,我找到了这个例子,但我不明白这意味着什么:
filtered_files=`echo "$files" | sed -e 's/^\.\///g'`
特别是在' -e'之后传递给sed
的论点。
答案 0 :(得分:2)
这是一个坏榜样;你不应该遵循它。
s/pattern/replacement/flags
是sed
命令,在man sed
中详细介绍。在这种情况下,pattern
是正则表达式; replacement
是什么样的模式被替换为何时/何时找到; flags
描述了如何进行替换的详细信息。
在这种情况下,s/^\.\///g
按如下方式细分:
s
是正在运行的sed
命令。/
是用于分隔此命令各部分的印记。 (任何角色都可以用作一个印记,选择使用/
作为这个表达的人是慈善的,不会考虑他们在做什么很辛苦)。^\.\/
是要替换的模式。 ^
意味着这只会在开头时替换任何内容; \.
只匹配一个句点,与.
匹配(这是匹配任何字符的正则表达式);并且\/
仅匹配/
(vs /
,这将继续执行此sed命令的下一部分,即选定的sigil。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'`)
用bash builtin替换sed
:
# This is much faster than shelling out to any external tool
filtered_files=${files//.\//}
而不是运行
files=$(find .)
...代替:
files=( )
while IFS= read -r -d '' filename; do
files+=( "$filename" )
done < <(find . -print0)
将文件存储在数组中;它看起来很复杂,但它更安全 - 即使文件名包含空格,引号字符,换行文字等也能正常工作。
此外,这意味着您可以执行以下操作:
# Remove the leading ./ from each name; don't remove ./ at any other position in a name
filtered_files=( "${files[@]#./}" )
这意味着名为
的文件./foo/this directory name (which has spaces) ends with a period./bar
将正确转换为
foo/this directory name (which has spaces) ends with a period./bar
而不是
foo/this directory name (which has spaces) ends with a periodbar
......原始方法会发生这种情况。
答案 1 :(得分:0)
man sed
。特别是:
-e script, --expression=script
add the script to the commands to be executed
和
s/regexp/replacement/
Attempt to match regexp against the pattern space. If success-
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
在这种情况下,它会用空字符串替换行开头./
的任何出现,换句话说,将其删除。