用于计算文件中字符串出现次数的 Bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18832297/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 06:35:12  来源:igfitidea点击:

Bash script to count the number of occurances of a string in a file

bashif-statement

提问by case

I have this function in my Bash script

我的 Bash 脚本中有这个功能

 if [ $numberOne -gt 10 ]
        then
                echo "$numberOne has occurred over 10 times"
                echo "email me numberOne"

        elif [ $numberTwo -gt 4 ]
        then    echo "$numberTwo has occurred over 4 times"
                echo "email me numberTwo"

        elif [ $numberThree -gt 4 ]
        then    echo "$numberThree has occurred over 4 times"
                echo "email me numberThree"

        elif [ $numberFour -gt 5 ]
        then    echo "$numberFour has occurred over 5 times"
                echo "email me numberFour"

        else    echo "nothing found yet"
                exit


        fi

}

Info: I am port checking. I run a script every minute. When a port is found to be used I write it to a file and then read the file. The number of times it's found equates to minutes. 4 times is 4 minutes, I want to know if the port is active more that a number of minutes.

信息:我正在检查端口。我每分钟运行一个脚本。当发现使用端口时,我将其写入文件,然后读取该文件。找到它的次数等于分钟。4 次是 4 分钟,我想知道端口是否处于活动状态超过分钟数。

What I want to do:

我想做的事:

3 numbers will populate a file. At some point one of them will be present more than 4 times and then the rest will also appear. At that point I want an alert when the first of them occurs or [all of them after the first occurrence]. Ideally the alert will be like this: "NumberOne has been open for 4 minutes". And after 1 minute it will be "5 minutes"-until I stop it or a threshold is reached, I don't know yet.

3 个数字将填充一个文件。在某些时候,其中一个将出现 4 次以上,然后其余的也将出现。那时我想要一个警报,当它们中的第一个发生或 [第一次发生后的所有]。理想情况下,警报应该是这样的:“NumberOne 已打开 4 分钟”。1 分钟后将是“5 分钟”——直到我停止它或达到阈值,我还不知道。

The problem: The problem here is that when NumberOne occurs more than 10 times AND NumberTwo occurs 4 times after that it only echoes NumberTwo.

问题:这里的问题是,当 NumberOne 出现 10 次以上且 NumberTwo 出现 4 次后,它只回显 NumberTwo。

I thought I could use continueafter each then, but I can't!

我以为我可以continue在 each 之后使用then,但我不能!

Also: my NumberOne variable. NumberOne=$(grep -wc "port=51555" monitor.txt)

另外:我的 NumberOne 变量。 NumberOne=$(grep -wc "port=51555" monitor.txt)

回答by konsolebox

To get the number of occurrences a string has on a file, use grep -c:

要获取字符串在文件中出现的次数,请使用grep -c

grep -c something file

An example application to this is:

对此的一个示例应用是:

file="/path/to/file"
numberOne_string="something"
numberOne=$(grep -c "$numberOne_string" "$file")

And about your logic the best option I think could only be:

关于你的逻辑,我认为最好的选择只能是:

if [[ numberOne -gt 10 || numberTwo -gt 4 || numberThree -gt 4 || numberFour -gt 5 ]]; then
    if [[ numberOne -gt 10 ]]; then
        echo "$numberOne has occurred over 10 times"
        echo "email me numberOne"
    fi
    if [[ numberTwo -gt 4 ]]; then
        echo "$numberTwo has occurred over 4 times"
        echo "email me numberTwo"
    fi
    if [[ numberThree -gt 4 ]]; then
        echo "$numberThree has occurred over 4 times"
        echo "email me numberThree"
    fi
    if [[ numberFour -gt 5 ]]; then
        echo "$numberFour has occurred over 5 times"
        echo "email me numberFour"
    fi
else
    echo "nothing found yet"
fi

Or a negated version of it.

或者它的否定版本。

Another requires a variable:

另一个需要一个变量:

nothing_found=true
if [[ numberOne -gt 10 ]]; then
    echo "$numberOne has occurred over 10 times"
    echo "email me numberOne"
    nothing_found=false
fi
if [[ numberTwo -gt 4 ]]; then
    echo "$numberTwo has occurred over 4 times"
    echo "email me numberTwo"
    nothing_found=false
fi
if [[ numberThree -gt 4 ]]; then
    echo "$numberThree has occurred over 4 times"
    echo "email me numberThree"
    nothing_found=false
fi
if [[ numberFour -gt 5 ]]; then
    echo "$numberFour has occurred over 5 times"
    echo "email me numberFour"
    nothing_found=false
fi
if [[ $nothing_found == true ]]; then
    echo "nothing found yet"
fi

回答by deivid

You are checking different variables... you don't need elifthere... Change it with independent if's. For example:

您正在检查不同的变量......你不需要elif那里......用独立if的改变它。例如:

if [ $numberOne -gt 10 ]
then
    echo "$numberOne has occurred over 10 times"
    echo "email me numberOne"
fi

if [ $numberTwo -gt 4 ]
then
    echo "$numberTwo has occurred over 4 times"
    echo "email me numberTwo"
if

if [ $numberThree -gt 4 ]
then
    echo "$numberThree has occurred over 4 times"
    echo "email me numberThree"
fi

if [ $numberThree -gt 5 ]
then
    echo "$numberFour has occurred over 5 times"
    echo "email me numberFour"
fi

if [ $numberOne -le 10 -a $numberTwo -le 4 -a $numberThree -le 4 -a $numberFour -le 5 ]
then
    echo "nothing found yet"
    exit
fi

回答by tripleee

Here is a refactoring which reduces code duplication.

这是减少代码重复的重构。

found=false
while read variable count; do
    value=${!$variable}
    if [ "$value" -gt "$count" ]; then
        echo "$value occurred more than $count times"
        echo "email me $variable"
        found=true
    fi
done <<____HERE
    numberOne  10
    numberTwo   4
    numberThree 4
    numberFour  5
____HERE

if ! $found; then
    echo "Nothing found yet"
fi

If you don't have Bash, you can use eval value="\$$variable"instead.

如果你没有 Bash,你可以用它eval value="\$$variable"代替。

If you want to populate the variables on the fly, you could do the grep -cinside the loop, and put e.g. a regex, or just the port number, in the first column of the here document instead.

如果您想即时填充变量,您可以grep -c在循环内部进行,并在此处文档的第一列中放置例如正则表达式或仅端口号。