Bash 脚本 - 修改命令的输出并打印到文件中

Bash script - Modify output of command and print into file

我正在尝试获取指定命令的文本输出,以某种方式对其进行修改(例如在输出前添加前缀)并打印到文件(.txt 或 .log)中

LOG_FILE=...
LOG_ERROR_FILE=..
command_name >> ${LOG_FILE} 2>> ${LOG_ERROR_FILE}

我想在一行中完成修改命令 return 并将其打印到文件中。 错误输出和正常输出情况相同

我是 bash 脚本的初学者,所以请理解。

管道 | and/or 重定向 > 似乎是答案。

所以,作为一个伪造的例子来说明我的意思:要获得命令 ip a 吐出的所有接口,您可以将其通过管道传输到处理命令并将输出重定向到文件中。

ip a | awk -F': *' '/^[0-9]/ { print  }' > my_file.txt

如果您希望将其发送到单独处理,您可以重定向到 sub-shell:

$ command -V cd curl bogus > >(awk '{print $NF}' > stdout.txt) 2> >(sed 's/.*\s\(\w\+\)://' > stderr.txt)
$ cat stdout.txt 
builtin
(/usr/bin/curl)
$ cat stderr.txt 
bogus not found

但为了可读性,在单独的步骤中处理可能会更好:

$ command -V cd curl bogus >stdout.txt 2>stderr.txt
$ sed -i 's/.*\s//' stdout.txt
$ sed -i 's/.*\s\(\w\+\)://' stderr.txt
$ cat stdout.txt 
builtin
(/usr/bin/curl)
$ cat stderr.txt 
bogus not found

有无数种方法可以满足您的要求,我想情况必须决定使用什么,但这是一个开始。

创建一个函数来执行命令并将标准输出捕获到变量。

function execCommand(){
  local command="$@"
  {
    IFS=$'\n' read -r -d '' STDERR;
    IFS=$'\n' read -r -d '' STDOUT;
  } < <((printf '[=10=]%s[=10=]' "$($command)" 1>&2) 2>&1)
}

function testCommand(){
    grep foo bar
    echo "return code $?"
}

execCommand testCommand
echo err: $STDERR
echo out: $STDOUT

execCommand "touch /etc/foo"
echo err: $STDERR
echo out: $STDOUT

execCommand "date"
echo err: $STDERR
echo out: $STDOUT

输出

err: grep: bar: No such file or directory
out: return code 2
err: touch: cannot touch '/etc/foo': Permission denied
out:
err:
out: Mon Jan 31 16:29:51 CET 2022

现在您可以修改 $STDERR & $STDOUT

execCommand testCommand &&  { echo "$STDERR" > err.log; echo "$STDOUT" > out.log; }

解释:Look at the answer from madmurphy

要修改输出并将其写入文件,同时以不同的方式修改错误流并写入不同的文件,您只需要适当地操作文件描述符。例如:

#!/bin/sh
# A command that writes trivial data to both stdout and stderr
cmd() {
        echo 'Hello stdout!'
        echo 'Hello stderr!' >&2
}


# Filter both streams and redirect to different files
{ cmd 2>&1 1>&3 | sed 's/stderr/cruel world/' > "$LOG_ERROR_FILE"; } 3>&1 |
     sed 's/stdout/world/' > "$LOG_FILE"

该技术是将错误流重定向到标准输出,以便它可以流入管道 (2>&1),然后将输出流重定向到辅助文件描述符,该辅助文件描述符被重定向到不同的管道.

您可以通过将文件重定向移动到更早的 exec 调用来稍微清理一下。例如:

#!/bin/sh
cmd() {
        echo 'Hello stdout!'
        echo 'Hello stderr!' >&2
}

exec > "$LOG_FILE"
exec 2> "$LOG_ERROR_FILE"

# Filter both streams and redirect to different files
{ cmd 2>&1 1>&3 | sed 's/stderr/cruel world/' >&2; } 3>&1 | sed 's/stdout/world/'