Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 管道中的Bash测试会导致奇怪的行为_Linux_Bash_Shell_Pipe_Echo - Fatal编程技术网

Linux 管道中的Bash测试会导致奇怪的行为

Linux 管道中的Bash测试会导致奇怪的行为,linux,bash,shell,pipe,echo,Linux,Bash,Shell,Pipe,Echo,我正在尝试为bash编写一个彩色输出库,其中包含各种样式选项,允许使用重定向进行着色和样式设置 e、 g echo“Red”| Red输出红色文本 及 echo“Bold”| Bold输出粗体文本 及 回显“黄色粗体”|黄色粗体输出粗体黄色文本 到目前为止,我编写的代码如下: #shellcheck shell=bash # set debug # set -o xtrace # number of colors supported __colors=$(tput colors 2>

我正在尝试为bash编写一个彩色输出库,其中包含各种样式选项,允许使用重定向进行着色和样式设置

e、 g

echo“Red”| Red
输出红色文本

echo“Bold”| Bold
输出粗体文本

回显“黄色粗体”|黄色粗体
输出粗体黄色文本

到目前为止,我编写的代码如下:

#shellcheck shell=bash

# set debug
# set -o xtrace

# number of colors supported
__colors=$(tput colors 2> /dev/null)
# colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"
# style
__default="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"


function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    # check if stoud is terminal and terminal supports colors
    [[ -t 1 ]] && \
    [[ -n $__colors ]] && \
    [[ $__colors -ge 8 ]]
  fi
}

function __style() {
  read -r input
  if has_colors; then
    echo -e "$1" "$input" "$__default"
  else
    echo -e "$input"
  fi
}

function black() {
  __style "$__black"
}

function red() {
  __style "$__red"
}

function green() {
  __style "$__green"
}

function yellow() {
  __style "$__yellow"
}

function blue() {
  __style "$__blue"
}

function magenta() {
  __style "$__magenta"
}

function cyan() {
  __style "$__cyan"
}

function white() {
  __style "$__white"
}

function bold() {
  __style "$__bold"
}

function underline() {
  __style "$__underline"
}
#shellcheck shell=bash

# set debug
# set -xv

# number of colors supported
__colors=$(tput colors 2> /dev/null)

# foreground colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"

# background colors
__bg_black="$(tput setab 0)"
__bg_red="$(tput setab 1)"
__bg_green="$(tput setab 2)"
__bg_yellow="$(tput setab 3)"
__bg_blue="$(tput setab 4)"
__bg_magenta="$(tput setab 5)"
__bg_cyan="$(tput setab 6)"
__bg_white="$(tput setab 7)"

# style
__reset="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"

function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    [[ -t 1 ]] && [[ -n $__colors ]] && [[ $__colors -ge 8 ]]
  fi
}

function __format() {
  local format="$1"
  local next="${2:-}" # next formatting function e.g. underline
  if has_colors; then
    echo -en "$format"
    if [[ -n $next ]]; then
      shift 2
      tee | "$next" "$@"
    else
      tee
      echo -en "$__reset"
    fi
  else
    tee #print output
  fi
}

function black() { __format "$__black" "$@"; }
function red() { __format "$__red" "$@"; }
function green() { __format "$__green" "$@";}
function yellow() { __format "$__yellow" "$@"; }
function blue() { __format "$__blue" "$@"; }
function magenta() { __format "$__magenta" "$@";}
function cyan() { __format "$__cyan"  "$@";}
function white() { __format "$__white"  "$@";}

function bg_black() { __format "$__bg_black" "$@"; }
function bg_red() { __format "$__bg_red" "$@"; }
function bg_green() { __format "$__bg_green" "$@";}
function bg_yellow() { __format "$__bg_yellow" "$@"; }
function bg_blue() { __format "$__bg_blue" "$@"; }
function bg_magenta() { __format "$__bg_magenta" "$@";}
function bg_cyan() { __format "$__bg_cyan"  "$@";}
function bg_white() { __format "$__bg_white"  "$@";}

function bold() { __format "$__bold"  "$@";}
function underline() { __format "$__underline" "$@"; }
设置颜色=始终输出转义码。另一方面,COLOR=auto执行一些检查,以确保当前stdout是终端并且终端支持颜色

问题是使用多个样式选项似乎不起作用。它始终应用最后一个样式选项。例如:

echo“Yellow bold”| Yellow | bold
输出粗体文本,但不输出黄色

另一方面:

echo“Bold yellow”| Bold | yellow
输出黄色文本,但不输出粗体文本

有趣的是;设置COLOR=似乎总是很好地工作。因此,我执行的测试似乎是为了确定stdout是否是终端
[[-t1]]
导致了这种情况。我不确定这是否是因为该测试有某种延迟。但是当我删除
[[-t1]]
位时,它就工作了


你知道我怎样才能做到这一点吗?不是Bash专家,也不知道shell是如何工作的。这里相当混乱。

头脑清醒地看待这一点,我发现我的方法存在问题

[[-t1]]
测试
stdout
是否为终端,当我输入两个函数,如
回显“Hello”| yellow | bold
[-t1]]
时,通过函数
黄色
表示输出不是终端时,
为false

这是因为函数(黄色)的输出通过管道传输到第二个函数(粗体)。这就是为什么它不输出黄色的转义码,只输出输入

因此,如果我继续使用管道连接到另一个函数,如
echo“Hello”| yellow | bold | underline
,它只会在输出中加下划线

这似乎是一种用颜色输出的好方法,但现在我必须改变我的方法,除非有办法知道当前运行的函数是否正在被管道传输而不是重定向

编辑

显示了一种检测命令是否被重定向或管道传输的方法

但最终,这种方法似乎不太可行,因为如果我在管道中不禁用颜色,它将在管道连接到另一个命令时输出颜色代码,而该命令不是另一个输出样式功能;这可能是一种边缘情况,但解决方案仍然不是100%无故障的

编辑解决方案:

改变了方法。使用“下一个格式”选项作为第一个的参数,而不是一个接一个地使用管道格式,如下所示

echo“Hello”|黄色粗体下划线

最终代码如下:

#shellcheck shell=bash

# set debug
# set -o xtrace

# number of colors supported
__colors=$(tput colors 2> /dev/null)
# colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"
# style
__default="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"


function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    # check if stoud is terminal and terminal supports colors
    [[ -t 1 ]] && \
    [[ -n $__colors ]] && \
    [[ $__colors -ge 8 ]]
  fi
}

function __style() {
  read -r input
  if has_colors; then
    echo -e "$1" "$input" "$__default"
  else
    echo -e "$input"
  fi
}

function black() {
  __style "$__black"
}

function red() {
  __style "$__red"
}

function green() {
  __style "$__green"
}

function yellow() {
  __style "$__yellow"
}

function blue() {
  __style "$__blue"
}

function magenta() {
  __style "$__magenta"
}

function cyan() {
  __style "$__cyan"
}

function white() {
  __style "$__white"
}

function bold() {
  __style "$__bold"
}

function underline() {
  __style "$__underline"
}
#shellcheck shell=bash

# set debug
# set -xv

# number of colors supported
__colors=$(tput colors 2> /dev/null)

# foreground colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"

# background colors
__bg_black="$(tput setab 0)"
__bg_red="$(tput setab 1)"
__bg_green="$(tput setab 2)"
__bg_yellow="$(tput setab 3)"
__bg_blue="$(tput setab 4)"
__bg_magenta="$(tput setab 5)"
__bg_cyan="$(tput setab 6)"
__bg_white="$(tput setab 7)"

# style
__reset="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"

function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    [[ -t 1 ]] && [[ -n $__colors ]] && [[ $__colors -ge 8 ]]
  fi
}

function __format() {
  local format="$1"
  local next="${2:-}" # next formatting function e.g. underline
  if has_colors; then
    echo -en "$format"
    if [[ -n $next ]]; then
      shift 2
      tee | "$next" "$@"
    else
      tee
      echo -en "$__reset"
    fi
  else
    tee #print output
  fi
}

function black() { __format "$__black" "$@"; }
function red() { __format "$__red" "$@"; }
function green() { __format "$__green" "$@";}
function yellow() { __format "$__yellow" "$@"; }
function blue() { __format "$__blue" "$@"; }
function magenta() { __format "$__magenta" "$@";}
function cyan() { __format "$__cyan"  "$@";}
function white() { __format "$__white"  "$@";}

function bg_black() { __format "$__bg_black" "$@"; }
function bg_red() { __format "$__bg_red" "$@"; }
function bg_green() { __format "$__bg_green" "$@";}
function bg_yellow() { __format "$__bg_yellow" "$@"; }
function bg_blue() { __format "$__bg_blue" "$@"; }
function bg_magenta() { __format "$__bg_magenta" "$@";}
function bg_cyan() { __format "$__bg_cyan"  "$@";}
function bg_white() { __format "$__bg_white"  "$@";}

function bold() { __format "$__bold"  "$@";}
function underline() { __format "$__underline" "$@"; }

以清醒的头脑看待这一点,我发现我的方法存在问题

[[-t1]]
测试
stdout
是否为终端,当我输入两个函数,如
回显“Hello”| yellow | bold
[-t1]]
时,通过函数
黄色
表示输出不是终端时,
为false

这是因为函数(黄色)的输出通过管道传输到第二个函数(粗体)。这就是为什么它不输出黄色的转义码,只输出输入

因此,如果我继续使用管道连接到另一个函数,如
echo“Hello”| yellow | bold | underline
,它只会在输出中加下划线

这似乎是一种用颜色输出的好方法,但现在我必须改变我的方法,除非有办法知道当前运行的函数是否正在被管道传输而不是重定向

编辑

显示了一种检测命令是否被重定向或管道传输的方法

但最终,这种方法似乎不太可行,因为如果我在管道中不禁用颜色,它将在管道连接到另一个命令时输出颜色代码,而该命令不是另一个输出样式功能;这可能是一种边缘情况,但解决方案仍然不是100%无故障的

编辑解决方案:

改变了方法。使用“下一个格式”选项作为第一个的参数,而不是一个接一个地使用管道格式,如下所示

echo“Hello”|黄色粗体下划线

最终代码如下:

#shellcheck shell=bash

# set debug
# set -o xtrace

# number of colors supported
__colors=$(tput colors 2> /dev/null)
# colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"
# style
__default="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"


function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    # check if stoud is terminal and terminal supports colors
    [[ -t 1 ]] && \
    [[ -n $__colors ]] && \
    [[ $__colors -ge 8 ]]
  fi
}

function __style() {
  read -r input
  if has_colors; then
    echo -e "$1" "$input" "$__default"
  else
    echo -e "$input"
  fi
}

function black() {
  __style "$__black"
}

function red() {
  __style "$__red"
}

function green() {
  __style "$__green"
}

function yellow() {
  __style "$__yellow"
}

function blue() {
  __style "$__blue"
}

function magenta() {
  __style "$__magenta"
}

function cyan() {
  __style "$__cyan"
}

function white() {
  __style "$__white"
}

function bold() {
  __style "$__bold"
}

function underline() {
  __style "$__underline"
}
#shellcheck shell=bash

# set debug
# set -xv

# number of colors supported
__colors=$(tput colors 2> /dev/null)

# foreground colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"

# background colors
__bg_black="$(tput setab 0)"
__bg_red="$(tput setab 1)"
__bg_green="$(tput setab 2)"
__bg_yellow="$(tput setab 3)"
__bg_blue="$(tput setab 4)"
__bg_magenta="$(tput setab 5)"
__bg_cyan="$(tput setab 6)"
__bg_white="$(tput setab 7)"

# style
__reset="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"

function has_colors() {
  COLOR=${COLOR:-auto}
  if [[ $COLOR = 'never' ]]; then
    return 1
  elif [[ $COLOR = 'always' ]]; then
    return 0
  else
    [[ -t 1 ]] && [[ -n $__colors ]] && [[ $__colors -ge 8 ]]
  fi
}

function __format() {
  local format="$1"
  local next="${2:-}" # next formatting function e.g. underline
  if has_colors; then
    echo -en "$format"
    if [[ -n $next ]]; then
      shift 2
      tee | "$next" "$@"
    else
      tee
      echo -en "$__reset"
    fi
  else
    tee #print output
  fi
}

function black() { __format "$__black" "$@"; }
function red() { __format "$__red" "$@"; }
function green() { __format "$__green" "$@";}
function yellow() { __format "$__yellow" "$@"; }
function blue() { __format "$__blue" "$@"; }
function magenta() { __format "$__magenta" "$@";}
function cyan() { __format "$__cyan"  "$@";}
function white() { __format "$__white"  "$@";}

function bg_black() { __format "$__bg_black" "$@"; }
function bg_red() { __format "$__bg_red" "$@"; }
function bg_green() { __format "$__bg_green" "$@";}
function bg_yellow() { __format "$__bg_yellow" "$@"; }
function bg_blue() { __format "$__bg_blue" "$@"; }
function bg_magenta() { __format "$__bg_magenta" "$@";}
function bg_cyan() { __format "$__bg_cyan"  "$@";}
function bg_white() { __format "$__bg_white"  "$@";}

function bold() { __format "$__bold"  "$@";}
function underline() { __format "$__underline" "$@"; }

问题是在
黄色|粗体
中,
黄色
的标准符号不是tty。您不应该签入每个颜色函数,而应该在主脚本中签入一次,并设置一个变量,使所有函数use@that另一个人,这正是我检查它的原因。如果我检查一次并将输出重定向到一个文件,它将带有颜色转义码。我不想看到set-xv输出,您的问题似乎来自这样一个事实:粗体(假设它是第二个)在样式内的echo-e行之前被调用,并接收原始字符串的副本,因此您可以在两者之间进行任意多的更改,结果将始终是标准文本粗体。不知何故,您需要让每个管道依次接收数据(不确定最佳方法)。您可以查看wait命令??当您确实需要某种三向区分(终端与文件与管道)时,您正在进行双向区分(终端与非终端)。问题是在
黄色|粗体
中,
黄色
的标准输出不是tty。您不应该签入每个颜色函数,而应该在主脚本中签入一次,并设置一个变量,使所有函数use@that另一个人,这正是我检查它的原因。如果我检查一次并将输出重定向到一个文件,它将带有颜色转义码。我不想看到set-xv输出,您的问题似乎来自这样一个事实,即在使用