在字符串上运行sed,在"<<<"上使用"echo"+"pipe"的好处

Sig*_*ius 3 io bash sed

通常我看到人们使用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"

  1. 可移植性

    正如您所指出的那样,<<<在POSIX sh中不可用; 这是一个ksh扩展,也可以在bash和zsh中使用.

    也就是说,如果你需要便携性,那么多线等价物并不遥远:

    ... <<EOF
    $s
    EOF
    
    Run Code Online (Sandbox Code Playgroud)
  2. 磁盘使用情况

    正如当前由bash实现的(以及作为要更改的实现细节),<<<创建一个临时文件,填充,重新定向和重定向.如果您TEMPDIR不在内存文件系统中,这可能会更慢,或者可能会产生客户流失.

  3. 流程开销

    管道,如在中echo foo | ...,创建一个子shell - 它会分离一个全新的进程,负责运行echo然后退出.当您运行时result=$(echo "$s" | ...),该管道本身位于您的父shell的子shell中,并且 shell的输出由父级读取.

    现代unixlikes尽最大努力尽可能地fork()降低子流程的开销,但即使这样,它也可以在循环中完成的操作中加起来 - 而在像Cygwin这样的平台上它可能更加重要.

  4. 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)


che*_*ner 5

sed如果可以帮助的话,根本不使用它(参见 Charles Duffy 的回答);将字符串放入变量中,并让 shell 通过 POSIX 兼容的参数扩展来完成此操作。

$ s="./asdf"
$ echo "${s#./}"
asdf
Run Code Online (Sandbox Code Playgroud)