Linux 将长单行命令转换为bash shell脚本

Linux 将长单行命令转换为bash shell脚本,linux,bash,shell,awk,Linux,Bash,Shell,Awk,我正在使用crontab中的以下命令: nice --20 iperf3 -c somelocation.com -f k | while IFS= read -r line; do echo "$(date) $line"; done | tee onespeed.txt | tee -a speeds.txt; sleep 30 ;cat onespeed.txt | grep sender >> concentrated.txt; sleep 2 ;cat onespeed.t

我正在使用crontab中的以下命令:

nice --20 iperf3 -c somelocation.com -f k | while IFS= read -r line; do echo "$(date) $line"; done | tee onespeed.txt | tee -a speeds.txt; sleep 30 ;cat onespeed.txt | grep sender >> concentrated.txt; sleep 2 ;cat onespeed.txt | grep sender | awk -F' ' '{print $13}' | while IFS= read -r line; do echo "$(date) $line"; done | tee onerawspeed.txt | tee -a rawspeeds.txt
我知道这项工作可以用一种更加优雅的方式来完成,但我想知道我是如何把它分解的,这样它的结构就可以作为bashshell脚本了

具体来说,我专注于在多行上构建它,以便它更具可读性

nice --20 iperf3 -c somelocation.com -f k | while IFS= read -r line; do 
echo "$(date) $line" 
done | tee onespeed.txt | tee -a speeds.txt
sleep 30 
grep "sender" onespeed.txt >> concentrated.txt
sleep 2 
awk -F' ' '/sender/ {print $13}' onespeed.txt | while IFS= read -r line; do
echo "$(date) $line"
done | tee onerawspeed.txt | tee -a rawspeeds.txt
编辑: 我已经根据评论更新了脚本

编辑:
我已经按照注释建议更新了脚本

,因为不清楚您真正想要在所有这些输出文件中放入什么,我将给出一个如何将不同值写入不同文件的示例

iperf3产生的每间隔比特率p/sec和平均比特率可单独放入如下文件:

$ cat tst.awk
BEGIN {OFS="\t";f1="speed.txt";f2="sender.txt"}
$6~/MBytes/{print strftime(), $7 >> f1; close(f1)}
/sender/{print strftime(), $7 >> f2; close(f2)}
$ iperf3 -c server -f k --forceflush | awk -f tst.awk
可以这样称呼:

$ cat tst.awk
BEGIN {OFS="\t";f1="speed.txt";f2="sender.txt"}
$6~/MBytes/{print strftime(), $7 >> f1; close(f1)}
/sender/{print strftime(), $7 >> f2; close(f2)}
$ iperf3 -c server -f k --forceflush | awk -f tst.awk
或者,在一行中:

 iperf3 -c server -f k --forceflush | awk -v f1=speed.txt -v f2=sender.txt \
    'BEGIN{OFS="\t"}                                          \
     $6~/MBytes/{print strftime(), $7 >> f1; close(f1)}       \
     /sender/{print strftime(), $7 >> f2; close(f2)}'

将系统日期和比特率打印到每个文件,按\t拆分。您需要iperf3的
forceflush
选项来防止输出缓冲,这将导致awk脚本为每一行打印相同的时间戳。

由于不清楚您真正想要在所有这些输出文件中放置什么,我将给出一个如何将不同值写入不同文件的示例

iperf3产生的每间隔比特率p/sec和平均比特率可单独放入如下文件:

$ cat tst.awk
BEGIN {OFS="\t";f1="speed.txt";f2="sender.txt"}
$6~/MBytes/{print strftime(), $7 >> f1; close(f1)}
/sender/{print strftime(), $7 >> f2; close(f2)}
$ iperf3 -c server -f k --forceflush | awk -f tst.awk
可以这样称呼:

$ cat tst.awk
BEGIN {OFS="\t";f1="speed.txt";f2="sender.txt"}
$6~/MBytes/{print strftime(), $7 >> f1; close(f1)}
/sender/{print strftime(), $7 >> f2; close(f2)}
$ iperf3 -c server -f k --forceflush | awk -f tst.awk
或者,在一行中:

 iperf3 -c server -f k --forceflush | awk -v f1=speed.txt -v f2=sender.txt \
    'BEGIN{OFS="\t"}                                          \
     $6~/MBytes/{print strftime(), $7 >> f1; close(f1)}       \
     /sender/{print strftime(), $7 >> f2; close(f2)}'

将系统日期和比特率打印到每个文件,按\t拆分。您需要iperf3的
forceflush
选项来防止输出缓冲,这将导致awk脚本为每行打印相同的时间戳。

将代码包装在任意函数
n(){one-liner\u code\u here;}
,然后运行
键入n
<代码>bash将丰富它的内容--特别有用的是它将如何缩进循环。但是
type
不会打断管道,并且会留下分号,所以这里有一些代码可以自动完成整个业务

假设一行程序是一个文件src。下面将src放入
$x
,然后为它生成一个函数n(这需要一个
eval
,对于函数中的带引号的字符串,它应该是无害的),然后
键入它,将它馈送到
sed
,忽略周围的括号,分解较长的管道并删除前导缩进和尾随
s,然后
unset
SN:



注意:
类型
还将当前环境中的任何
别名
转换为代码。因此,如果
grep
alias
ed到
grep--color=auto
,上面的每个
grep
都将被
grep--color=auto

替换为
n(){one-liner\u code\u here;}
,并运行
键入n
<代码>bash
将丰富它的内容--特别有用的是它将如何缩进循环。但是
type
不会打断管道,并且会留下分号,所以这里有一些代码可以自动完成整个业务

假设一行程序是一个文件src。下面将src放入
$x
,然后为它生成一个函数n(这需要一个
eval
,对于函数中的带引号的字符串,它应该是无害的),然后
键入它,将它馈送到
sed
,忽略周围的括号,分解较长的管道并删除前导缩进和尾随
s,然后
unset
SN:



注意:
类型
还将当前环境中的任何
别名
转换为代码。因此,如果
grep
alias
ed到
grep--color=auto
,上面的每个
grep
都将被
grep--color=auto
替换,只需替换
与换行符。此外,如果您已将编辑器设置为可以使用的内容,C-x C-e将在该编辑器中打开当前命令行,因此,您不必复制粘贴并错误地使用精心编制的命令行。我建议将
cat file | grep something
替换为
grep something file
cat file | grep something | awk-F'{print$13}'
替换为
awk-F'/something/{print$13}文件
。预期的输出是什么?我觉得你把事情弄得太复杂了。您需要4个输出文件:onerawspeed.txt、rawspeed.txt、onespeed.txt和concentrated.txt。“你想在每一个盒子里放什么?”塞勒斯:很好的建议,谢谢。我将把整个过程浓缩起来,但更多的是将这样的长命令分解成更可读的脚本:)只需替换
与换行符。此外,如果您已将编辑器设置为可以使用的内容,C-x C-e将在该编辑器中打开当前命令行,因此,您不必复制粘贴并错误地使用精心编制的命令行。我建议将
cat file | grep something
替换为
grep something file
cat file | grep something | awk-F'{print$13}'
替换为
awk-F'/something/{print$13}文件
。预期的输出是什么?我觉得你把事情弄得太复杂了。您需要4个输出文件:onerawspeed.txt、rawspeed.txt、onespeed.txt和concentrated.txt。“你想在每一个盒子里放什么?”塞勒斯:很好的建议,谢谢。我将把整个过程浓缩起来,但更多的是将这样的长命令分解成更可读的脚本:)没有任何
cat
程序调用是必需的,
grep
将文件名作为其最右边的参数。为什么不将
concentrated.txt
作为
awk
的输入,而不是再次执行相同的
grep
。它完美地回答了我的问题。
cat
程序调用都不是必需的,
grep
将文件名作为其最右边的参数。为什么不集中精神