bash和POSIX sh中set -x或“ $ @”值的回显日志的差异

时间:2019-01-07 17:45:44

标签: bash sh

我正在运行Ubuntu 16.04.5 LTS。我有以下脚本:

#!/bin/bash
set -x
for i in "$@"; do
    echo $i
done

运行它,我得到:

$ scripts/t.sh a b c\\nd
+ for i in "$@"
+ echo a
a
+ for i in "$@"
+ echo b
b
+ for i in "$@"
+ echo 'c\nd'
c\nd

如果我将shebang更改为#!/bin/sh,然后重新运行,则会得到:

$ scripts/t.sh a b c\\nd
+ set -x
+ echo a
a
+ echo b
b
+ echo c\nd
c
d

在bash情况下,换行符显示为set -x日志中的引号,而echo不解释换行符;使用sh时,该值显示为不带引号,并且解释换行符。这是预期的吗?为什么会有所不同?

1 个答案:

答案 0 :(得分:4)

set -x输出中的差异

POSIX不需要set -x来显示以任何特定方式引用的输出。来自matendie

  

在扩展命令之后和执行命令之前,外壳程序应将每个命令的跟踪信息写入标准错误。尚未确定是否跟踪了关闭跟踪的命令。

...并且在the POSIX specification for the set command中,PS4的定义如下:

  

在交互式外壳中执行执行跟踪(set -x)时,应在执行跟踪的每一行之前对该变量的值进行参数扩展,并写入标准错误。默认值为“ +”。 POSIX.1-2017的此卷仅针对支持“用户可移植性实用程序”选项的系统指定了变量的作用。

“ A trace”(跟踪)或“ the trace”(用于指定PS4之后的文本的唯一语言)含糊不清,以至于两个实现都同样兼容。


echo输出中的差异

允许

POSIX echo总是 遵守转义序列,而无需传递-e。 (实际上,不允许完全兼容POSIX的echo -e视为要打印的文本以外的任何其他内容,因此bash违反了规范-除非当同时启用xpg_echoposix运行时标志时,这是bash的echo唯一听见标准字母的情况。

如果您希望跨平台保持一致的行为,请使用printf '%s\n' "$foo"而不是echo "$foo"

完整引用the shell command language specification的APPLICATION USAGE部分,并强调:

  

除非所有{IX}(作为第一个参数)和转义序列都被省略,否则不可能在所有POSIX系统上可移植地使用echo

     

-n实用程序可用于如下模拟printf实用程序的任何传统行为(假设echo具有其标准值或未设置):      

      
  • 此版本的POSIX.1-2017中具有历史意义的系统V IFS和XSI实现的要求等效于:

    echo
  •   
  • BSD printf "%b\n" "$*" 等效于:

    echo
  •   
     

鼓励新应用使用if [ "X$1" = "X-n" ] then shift printf "%s" "$*" else printf "%s\n" "$*" fi 而不是printf

出于上面引用的粗体语言的目的,序列echo是一个“转义序列”。