如何将bash中的输入文件格式化为特殊格式?

时间:2015-01-07 06:57:33

标签: bash

我有一个文本文件,我通过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

     

...

所以我快到了。

3 个答案:

答案 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

解释:

  1. sys变量从第二个字段中提取数字 - sys1,sys3等(这将分别包含1,3)
  2. 将第一个字段以逗号分隔为数组a
  3. 的分隔符
  4. 根据需要使用a
  5. 循环打印字符串
  6. 忽略输入文件中的字段3。至少对于提供的输入,field2&amp; 3总是有相同的数字。

答案 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脚本。

感谢您提供的帮助。