简体   繁体   English

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

[英]Convert long single line command to a bash shell script

Im working on the following command in crontab: 我正在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

I understand that the job could be done in a far more elegant way but Im looking to find out how I go about breaking this down so that its structured properly to act as a bash shell script. 我知道可以用一种更为优雅的方式来完成这项工作,但是我希望找出如何分解它的方法,以使其结构合理以用作bash shell脚本。

Specifically Im focused on structuring it over multiple lines so that it is more readable. 我特别关注Im在多行结构上的结构,以使其更具可读性。

Since it's not clear what you really want to put in all those output files, I'll give an example of how to write separate values to different files. 由于尚不清楚您真正想要在所有这些输出文件中放入什么内容,因此我将举一个示例,说明如何将单独的值写入不同的文件。

The bitrate p/sec per interval and the average Bitrate that iperf3 produces can be put -separely- into a file like this: 每个间隔的比特率p / sec和iperf3产生的平均比特率可以-separely-放入如下文件中:

$ 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)}

which can be called like this: 可以这样称呼:

$ iperf3 -c server -f k --forceflush | awk -f tst.awk

or, in one line: 或者,一行:

 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)}'

which print sysdate and Bitrate to each file, split by \\t. 将sysdate和Bitrate打印到每个文件,并用\\ t分隔。 You'll need the forceflush option of iperf3 to prevent buffering of the output, which would cause the awk script to print the same timestamp for each line. 您需要使用forceflush选项来防止缓冲输出,这会导致awk脚本为每行打印相同的时间戳。

Wrap the code in an arbitrary function n() { one-liner_code_here ; } 将代码包装在任意函数n() { one-liner_code_here ; } n() { one-liner_code_here ; } , and run type n . n() { one-liner_code_here ; } ,然后type n bash will flesh a lot of it out -- particularly useful is how it'll indent loops. bash会充实很多内容-特别有用的是它如何缩进循环。 But type won't break up the pipes, and leaves semicolons behind, so here's some code to automate the whole business... 但是type不会破坏管道,并留下分号,因此这里有一些代码可以自动化整个业务...

Suppose the one-liner is a file src . 假设单线文件是文件src The following puts src into $x , then makes a function n for it, (this requires an eval which for a quoted string in a function should be harmless), and type s it, feeds that to sed which ignores the surrounding brackets, breaks up the longer pipes and removes the leading indents & trailing ; 下面将src放入$x ,然后为其创建函数n (这需要一个eval ,对于eval中带引号的字符串应无害),然后type s,将其输入sed ,而忽略周围的方括号,换行延长较长的管道,并消除领先的凹痕和拖尾; s, then unset s n : s,然后未unset s n

read x <src; eval n\(\) \{ "$x" \;\}
type n | sed -n '/^ /{s/^    //;/^[^ ]/s/| /|\n/g;s/\;$//;p}' ; unset -f n

Output: 输出:

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

Note: type will also convert any alias in the current environment to code. 注意: type还将当前环境中的任何alias转换为代码。 So if grep is alias ed to grep --color=auto , each grep above would be replaced with grep --color=auto . 因此,如果grepgrep --color=auto alias ,则上述每个grep都将替换为grep --color=auto

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

EDIT : I have updated the script, following the comments advices 编辑:我已经按照评论建议更新了脚本

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM