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



我试图获得指定命令的文本输出,以某种方式修改它(例如在输出前添加前缀(并打印到文件(.txt或.log(

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

我想在一行中修改将返回的命令并将其打印到文件中。错误输出和常规输出的情况相同。

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

创建一个函数来执行命令并捕获变量的sterr和stdout。

function execCommand(){
local command="$@"
{
IFS=$'n' read -r -d '' STDERR;
IFS=$'n' read -r -d '' STDOUT;
} < <((printf '%s' "$($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; }

说明:看看来自madmurphy 的答案

管道|和/或重定向>似乎就是答案。

因此,作为一个虚假的例子来展示我的意思:为了获得命令ip a吐出的所有接口,您可以将其通过管道传输到处理命令,并将输出重定向到文件中。

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

如果你想把它发送到单独的处理,你可以重定向到一个子外壳:

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

有无数种方法可以满足你们的要求,我想情况将不得不决定使用什么,但这里有一个开始。

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

#!/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"

该技术是将错误流重定向到stdout,以便它可以流入管道(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/'

最新更新