【问题标题】:How to count the frequency of an element in every line of a file with bash如何使用bash计算文件每一行中元素的频率
【发布时间】:2021-01-29 04:11:21
【问题描述】:

我有一个如下所示的文件:

1|2|3|4
1|2|3|4
1|2|3
1|2
1|2|3|4
1|2|3|4

我想要做的是计算| 在每一行中出现的频率并打印如下消息:所有行都有这个数量,除了这个有这个其他数量的行 em>。

所需的输出应该是这样的:

The "|" element appears 3 times in each line except in line 3 and 4 where it appears 2 and 1 times 

我是 bash 的新手,非常感谢您的帮助!

【问题讨论】:

  • 请将该示例输入的所需输出(无描述)添加到您的问题(无评论)。
  • 您尝试了哪些方法,又是如何失败的?
  • @choroba 我一直在使用此代码grep -o '|' filename | wc -l,但它正在计算一个 |出现在整个文件中,而不仅仅是在每一行中。

标签: bash count


【解决方案1】:

使用 awk:

awk -F\| '{ if (map[NF-1]!="") { map[NF-1]=map[NF-1]","NR } else { map[NF-1]=NR } } END { for (i in map) { printf  "lines %s have %s occurances of |\n",map[i],i } }' file

解释:

awk -F\| '{                                                         # Set the field delimiter to |
            if (map[NF-1]!="") { 
                map[NF-1]=map[NF-1]","NR                            # Create an array called map with the number of | occurrences (NF-1) as the index and line number (NR) as the value
            } 
            else { 
                map[NF-1]=NR                                         # We don't want to prefix a comma if this is the first entry in the array
            } 
            map1[NF-1]++
           } 
       END { 
             for (i in map) { 
                printf  "line(s) %s have %s occurrence(s) of |\n",map[i],i # At the end, print the contents of the array in the format required.
             }
             for (i in map1) {
                printf "%s line(s) have %s occurrence(s) of |, ",map1[i],i
             }
            printf "\n"
            }' file

输出:

line(s) 4 have 1 occurrence(s) of |
line(s) 3 have 2 occurrence(s) of |
line(s) 1,2,5,6 have 3 occurrence(s) of |

【讨论】:

  • 你知道我该怎么做一个计数器,所以我的输出会是这样的:10 lines have 1 occurrence(s) of |, 5 lines have 3 occurrence(s) of |
  • 尝试修改。
  • 我相信我并没有真正理解你最后的答案。
  • 我创建了另一个数组 map1,它由管道数索引并具有递增值。然后我在最后循环 map1。
  • 我收到此错误:awk: cmd. line:15: (FILENAME=starts_data_encoded.psv FNR=119615) 致命:没有足够的参数来满足格式字符串 `%s line(s) 有 %s 个 |, 119615' ^ 用完这个我>
【解决方案2】:

在 bash 中使用关联数组来跟踪频率:

#! /bin/bash
declare -A freq lines
line=1
while read -r bars ; do
    (( length=${#bars} ))
    (( ++freq["$length"] ))
    lines[$length]+=" $line"
    (( ++line ))
done < <( cat "$@" | tr -cd '\n|')

freqs=("${!freq[@]}")
max=${freqs[0]}
for length in "${!freq[@]}" ; do
    (( ${freq[$length]} > ${freq[$max]} )) && max=$length
done

echo 'The "|" element appears '$max' times in each line'

for k in "${!freq[@]}" ; do
    [[ $k == $max ]] && continue
    echo "except in line(s)${lines[$k]} where it appears $k time(s)"
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    相关资源
    最近更新 更多