我有一个文本文件,我通过bash脚本从各种服务器crontabs生成,看起来像这种格式:
0 sys1 server1
5 sys2 server2
2,3 sys3
0 sys3 server3
7 sys4 server4
...
我希望它能够形成这个:
0 sys1 server1
5 sys2 server2
2 sys3 server3
3 sys3 server3
0 sys3 server3
7 sys4 server4
...
我遇到的问题是,如果每个系统/服务器有两个数字或更多,并且每个服务器可能还有两个以上的crontab条目,它总是可以更改。
我的尝试是这样的:
rday_old=""
rsys_old=""
rser_old=""
[[ -e output ]] && rm output
while read -u5 -r -a line; do
rday=${line[0]}
rsys=${line[1]}
rser=${line[2]}
if [[ "$rsys_old" == "$rsys" ]]; then
echo "$rday_old $rsys_old $rser" >> output
else
echo "$rday $rsys $rser" >> output
fi
rday_old=$rday
rsys_old=$rsys
rser_old=$rser
done 5< input_file
问题显然是它不会像预期的那样工作。我不知道解决这个问题的最佳方法是什么。我的尝试并没有考虑到当crontab格式为2,3或者甚至2,4,5到7天(这将是一个*符号)时,需要拆分这一天。另外,我可能需要存储多个rday_old,rsys_old和rser_old。
我希望我以一种可以理解的方式陈述我的问题。 感谢您提前提供任何帮助。
编辑:
在@anishsane回答后,我修复了他的回答
cat input | awk '{sys=$2; ser=$3; split($1,a,","); for(i in a){print a[i]" " sys " " ser}}' > output
但现在输出结果:
0 sys1 server1
5 sys2 server2
2 sys3
3 sys3 server3
0 sys3 server3
7 sys4 server4
...
所以我快到了。
答案 0 :(得分:0)
这是一个Python解决方案:
#!/usr/bin/env python
import fileinput
import re
for line in fileinput.input():
matches = re.match('(\d),(\d) sys(\d+)', line)
if matches:
first, last, sys = matches.groups()
for ii in range(int(first), int(last) + 1):
print ii, 'sys' + sys, 'server' + sys
else:
print line,
它使用一个简单的正则表达式来匹配第一个字段中带有逗号的行。如果匹配,则从数字范围的开头到结尾打印行。否则打印原始行。
答案 1 :(得分:0)
gawk
方法:
$ cat srvlist
0 sys1 server1
5 sys2 server2
2,3 sys3
0 sys3 server3
7 sys4 server4
$ awk '{sys=gensub("sys","","",$2); split($1,a,","); for(i in a){print a[i] " sys" sys " server" sys}}' srvlist
0 sys1 server1
5 sys2 server2
2 sys3 server3
3 sys3 server3
0 sys3 server3
7 sys4 server4
解释:
sys
变量从第二个字段中提取数字 - sys1,sys3等(这将分别包含1,3)a
a
答案 2 :(得分:0)
现在解决了它:
[[ -e output ]] && rm output
tac input > rev_input
rser_old=""
while read -u5 -r -a line; do
rday=${line[0]}
rsys=${line[1]}
rser=${line[2]}
OIFS=$IFS
IFS=','
for x in $rday
do
[[ "$rser" == "" ]] && echo "$x $rsys $rser_old" >> output
[[ "$rser" != "" ]] && echo "$x $rsys $rser" >> output
done
rser_old=$rser
IFS=$OIFS
done 5< rev_input
输出现在显然是相反的,但这根本不重要,因为这部分只是一个步骤,输出现在将被处理为antoher脚本。
感谢您提供的帮助。