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/'
我正在尝试获取指定命令的文本输出,以某种方式对其进行修改(例如在输出前添加前缀)并打印到文件(.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/'