提取具有特定图案的部分线并使用bash求和

时间:2018-09-20 00:52:45

标签: regex bash sed pattern-matching

我正在学习bash脚本和命令,我需要一些有关此作业的帮助。

我有一个包含以下文本的txt文件,我需要这样做:

  1. 提取来宾姓名(1.1.1 ..)
  2. 汇总来宾结果,并输出包含结果的来宾名称。

我用sed和简单的正则表达式提取名称和数字,但是我不知道如何总结数字,因为来宾有多行记录,如您在txt文件中看到的那样。 注意:我无法使用awk进行处理

这是我的代码:

cat file.txt | sed -E 's/.*([0-9]{1}.[0-9]{1}.[0-9]{1}).*([0-9]{1})/\1 \2/'

结果是:

1.1.1 4
2.2.2 2
1.1.1 1
3.3.3 1
2.2.2 1

这是.txt文件:

Guest 1.1.1 have "4
Guest 2.2.2 have "2
Guest 1.1.1 have "1
Guest 3.3.3 have "1
Guest 2.2.2 have "1

,输出应为:

1.1.1 = 5
2.2.2 = 3
3.3.3 = 1

谢谢您

3 个答案:

答案 0 :(得分:0)

我知道您的老师不会允许您使用awk,但是,由于超出了这一练习的范围,您正在尝试学习如何编写shell脚本,因此,仅供参考,这就是您实际上如何在shell脚本中完成此工作的方法:

$ awk -F'[ "]' -v OFS=' = ' '{sum[$2]+=$NF} END{for (id in sum) print id, sum[id]}' file
3.3.3 = 1
2.2.2 = 3
1.1.1 = 5

这是bash内置的等效项,它可能会或可能不会是您在课堂上讨论的内容,因此可能会也可能不是您的老师所期望的:

$ cat tst.sh
#!/bin/env bash
declare -A sum

while read -r _ id _ cnt; do
    (( sum[$id] += "${cnt#\"}" ))
done < "$1"

for id in "${!sum[@]}"; do
    printf '%s = %d\n' "$id" "${sum[$id]}"
done

$ ./tst.sh file
1.1.1 = 5
2.2.2 = 3
3.3.3 = 1

有关我如何使用关联数组,请参见https://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/。它会比awk脚本慢几个数量级,并且我不能100%地确定它是防弹的(因为shell并非设计用于处理文本,因此存在很多警告和陷阱),但它对于您提供的输入。

答案 1 :(得分:0)

好的-由于这是一个课堂作业,所以我将告诉您我是如何做到的,并让您编写代码。

首先,我对文件进行了排序。然后,我一次只读取一行文件。如果名称更改,我将打印出先前的名称和计数,并将计数设置为该行上的值。如果名称没有更改,我会将值添加到计数中。

答案 2 :(得分:0)

第二个解决方案使用来宾名称作为索引,使用关联数组来保存计数。然后,您只需将新值添加到以来宾名称为索引的数组元素的计数中即可。

最后,遍历数组,打印出索引和值。

要短很多。