<分区>
通常我看到人们使用 sed 操作字符串,如下所示:
echo "./asdf" | sed -n -e "s%./%%p"
我最近了解到我还可以:
sed -n -e "s%./%%p" <<< "./asdf"
是否有理由避免后者? 例如,它是特定于 bash 的行为吗?
<分区>
通常我看到人们使用 sed 操作字符串,如下所示:
echo "./asdf" | sed -n -e "s%./%%p"
我最近了解到我还可以:
sed -n -e "s%./%%p" <<< "./asdf"
是否有理由避免后者? 例如,它是特定于 bash 的行为吗?
最佳答案
./
从路径的开头开始(或执行其他简单的字符串操作)?Bash 的内置语法称为 parameter expansion . ${s#./}
将展开$s
与任何前导 ./
在 shell 内部修剪,没有子进程或其他开销。 BashFAQ #100涵盖许多额外的字符串操作操作。
echo "$s" | ...
之间有什么区别?和 ... <<<"$s"
?便携性
如您所见,<<<
在 POSIX sh 中不可用;这是 bash 和 zsh 中也可用的 ksh 扩展。
也就是说,如果您需要可移植性,多行等价物就在不远处:
... <<EOF
$s
EOF
磁盘使用情况
目前由 bash 实现(并且作为实现细节可能会发生变化),<<<
创建一个临时文件,填充它,并从中重定向。如果你的TEMPDIR
不在内存文件系统上,这可能会更慢,或者可能会产生困惑。
处理开销
管道,如 echo foo | ...
, 创建一个 subshell -- 它派生出一个全新的进程,负责运行 echo
然后退出。当你运行时 result=$(echo "$s" | ...)
,然后该管道本身位于父 shell 的子 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" | ...
关于bash - 在字符串上运行 sed,使用 "echo"+ "pipe"优于 "<<<"的好处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41899075/