如何遍历输出并将结果格式化为新报告?

时间:2019-06-03 19:49:02

标签: linux bash shell

我正在处理一个脚本,以处理配置文件的输出,以使其产生有价值的数据。

输出格式为:

[header]
attribute1 = integer
attribute2 = integer
[header]
attribute1 = integer
attribute2 = integer
...

其中可能存在未知数量的节,这些节具有相同的两个属性(具有未知的整数值),但是具有不同的标头。

到目前为止,我只能生成不同的节数以将其用作循环计数器,但是我不确定如何循环输出,保持标头不变但将两个属性的整数值相加并将它们替换为具有新属性的新属性,例如

[header]
new_attribute = integer
[header]
new_attribute = integer

我已经查看了命令read,但不确定如何生成所需的报告。

3 个答案:

答案 0 :(得分:2)

while read header &&
      read name1 equal value1 &&
      read name2 equal value2
do
    echo "$header"
    echo "new_attribute = $((value1 + value2))"
done < input.cfg > output.cfg

此代码假定输入的格式完全符合规定。它不能可靠地处理错误的输入:格式错误的行,行丢失,意外的反斜杠等。

答案 1 :(得分:1)

请不要使用shell批量处理文本文件;它很慢而且不安全。我最喜欢的文本处理工具是Awk,您可以通过man awk了解更多信息。

在awk中,NR是指号码记录或行号。 %是“模”或余数,因此,如果我们知道只有三种记录,则可以很直率地编写所需的脚本。

尝试awk '{print NR%3, $0}' file来查看结构。

awk -F ' = ' '                                # Field Separator = space, equals, space
  NR%3 == 1 {print $0}                        # print header
  NR%3 == 2 {i=$2}                            # save second field as i
  NR%3 == 0 {print "new_attribute" FS i+$2}   # print string, field separator, and sum
' file

答案 2 :(得分:1)

使用专用库更强大。与依赖连续出现的行相比,尤其如此。

这是用Python编写的简短脚本。为特定的部分和属性添加测试以忽略或通过不变的测试将是微不足道的。

使用输入文件new.ini

$ cat test.ini
[header1]
attribute1 = 10
attribute2 = 12
[header2]
attribute1 = 23
attribute2 = 25

和脚本transform_ini.py

$ cat ini.py
#!/usr/bin/python3
import configparser
config = configparser.ConfigParser()
new_config = configparser.ConfigParser()

new_key = 'new_attribute'

config.read('test.ini')

for section in config.sections():
    val = 0

    for key in config[section]:
        val += int(config[section][key])

    new_config[section] = {}
    new_config[section][new_key] = str(val)

with open('new.ini', 'w') as configfile:
    new_config.write(configfile)

结果为new.ini

$ cat new.ini 
[header1]
new_attribute = 22

[header2]
new_attribute = 48

该脚本支持“映射协议访问”,因此需要Python 3.2或更高版本。我没有使用getint(),因为它似乎被归类为旧版API的一部分。

请注意,ConfigParser.read() closes the input file for you