通常我看到人们使用sed操作字符串如下:
echo "./asdf" | sed -n -e "s%./%%p"
Run Code Online (Sandbox Code Playgroud)
我最近了解到我也可以这样做:
sed -n -e "s%./%%p" <<< "./asdf"
Run Code Online (Sandbox Code Playgroud)
是否有理由避免后者?例如,它是特定于bash的行为吗?
Cha*_*ffy 10
./从路径的开头修剪(或执行其他简单的字符串操作)?Bash的内置语法称为参数扩展.${s#./}将$s随着./shell的任何前导修剪内部扩展,没有子进程或其他开销.BashFAQ#100涵盖了许多额外的字符串操作操作.
echo "$s" | ...和之间有什么区别... <<<"$s"?可移植性
正如您所指出的那样,<<<在POSIX sh中不可用; 这是一个ksh扩展,也可以在bash和zsh中使用.
也就是说,如果你需要便携性,那么多线等价物并不遥远:
... <<EOF
$s
EOF
Run Code Online (Sandbox Code Playgroud)磁盘使用情况
正如当前由bash实现的(以及作为要更改的实现细节),<<<创建一个临时文件,填充,重新定向和重定向.如果您TEMPDIR不在内存文件系统中,这可能会更慢,或者可能会产生客户流失.
流程开销
管道,如在中echo foo | ...,创建一个子shell - 它会分离一个全新的进程,负责运行echo然后退出.当您运行时result=$(echo "$s" | ...),该管道本身位于您的父shell的子shell中,并且该 shell的输出由父级读取.
现代unixlikes尽最大努力尽可能地fork()降低子流程的开销,但即使这样,它也可以在循环中完成的操作中加起来 - 而在像Cygwin这样的平台上它可能更加重要.
echo 虫子
最后但并非最不重要的 - <<<"$s"将s精确地表示变量的任何内容,除了它可以添加尾随换行符.相比之下,echo它在指定行为方面有很大的余地:它可以遵循反斜杠扩展或不依赖于对标准的可选XSI扩展的遵从性(以及存在或缺少广泛但完全不符合的扩展-e和/或运行时)禁用它的标志); -n标准不保证能够避免添加尾随换行符; &C.即使您使用的是管道,最好使用printf:
# emit *exactly* the contents of "$s", with no newline added
printf '%s' "$s" | ...
# emit the contents of "$s", with an added trailing newline
printf '%s\n' "$s" | ...
# emit the contents of "$s", with '\t', '\n', '\b' &c replaced, and no added newline
printf '%b' "$s" | ...
Run Code Online (Sandbox Code Playgroud)sed如果可以帮助的话,根本不使用它(参见 Charles Duffy 的回答);将字符串放入变量中,并让 shell 通过 POSIX 兼容的参数扩展来完成此操作。
$ s="./asdf"
$ echo "${s#./}"
asdf
Run Code Online (Sandbox Code Playgroud)