【问题标题】:Bash - Counting substrings in a stringBash - 计算字符串中的子字符串
【发布时间】:2014-10-06 09:00:06
【问题描述】:

我很难编写一个命令来计算子字符串在字符串中出现的次数。

与其将代码运行 10 次以下,我宁愿预先计算子字符串出现的次数,并根据其结果调整“for”:

这里可以看到代码:

CommandResult="Interface    Chipset     Driver     mon0    Unknown      iwlwifi - [phy0]wlan0       Unknown     iwlwifi - [phy0]"

for i in `seq 0 9`;
do
  InstanceID="mon"$i

  if echo "$CommandResult" | grep -q "$InstanceID"; then
    echo "found"
  fi
done

任何帮助将不胜感激!

谢谢,

【问题讨论】:

    标签: linux bash shell ubuntu


    【解决方案1】:

    随意尝试这个来获取号码:

    echo "$CommandResult" | tr " " "\n" | grep -c "$InstanceID"
    

    【讨论】:

    • 嗨赛勒斯。感谢您的回答。如何将结果捕获到变量中?我试过: NumberOfMatches="$CommandResult" | tr " " "\n" | grep -c "$searchString" 但它不起作用。谢谢!
    • NumberOfMatches=$(echo "$CommandResult" | tr " " "\n" | grep -c "$InstanceID")
    【解决方案2】:

    我会使用grep -o 从输出中提取所需的字符串:

    #!/bin/bash
    CommandResult="Interface    Chipset     Driver     mon0    Unknown      iwlwifi - [phy0]wlan0       Unknown     iwlwifi - [phy0]
    Interface    Chipset     Driver     mon12    Unknown      iwlwifi - [phy0]wlan0       Unknown     iwlwifi - [phy0]"
    
    for InstanceId in $(grep -o 'mon[0-9]\+' <<< "$CommandResult") ; do
        echo "found $InstanceId "$(grep -c "$InstanceId" <<< "$CommandResult")' times'
    done
    

    【讨论】:

      【解决方案3】:

      想分享另一个解决方案。 3,5 年后,但我猜迟到总比没有好。 ;)

      我正在编写一个必须执行相同操作的脚本,即获取字符串中子字符串的数量,我最初使用的是count=$(echo '$string' | grep -o ... | wc -l)
      我得到了我想要的,但是当循环遍历大约 1500 个文件,每个文件有 0...8000 行时,性能非常糟糕:脚本大约需要 49 分钟 才能完成。
      所以,我去寻找替代方法,最终找到了这个:

      InstanceId="mon0";
      tmp="${CommandResult//$InstanceId}"
      count=$(((${#CommandResult} - ${#tmp}) / ${#InstanceId}))
      

      在 8-9 分钟内得到相同的结果,但速度更快。

      解释:

      tmp="${CommandResult//$InstanceId}"
      

      这会从$CommandResult 中删除所有出现的$InstanceId 并将其放入tmp
      实际上,我们在这里使用子字符串替换,缺少替换字符串。子字符串替换的语法是${string//substring/replacement}(这会将所有出现的子字符串替换为替换)。

      count=$(((${#CommandResult} - ${#tmp}) / ${#InstanceId}))
      

      这给了我们$InstanceId$CommandResult 中出现的次数。
      ${#string} 给出了字符串长度,所以(${#CommandResult} - ${#tmp]) 是所有$InstanceId 出现的长度(请记住,我们删除了所有出现的@ 987654335@ 来自$CommandResult 并将结果放在$tmp)。
      然后我们只需用长度为$InstanceId 的减法除以得到$InstanceId 出现的次数。

      有关子字符串替换和字符串长度的更多信息,请参阅例如https://www.tldp.org/LDP/abs/html/string-manipulation.html.

      【讨论】:

      • count= 行中的括号不正确 - 但更改后,仍然无法使其与 bash 4.3 一起使用
      • 哦,确实有一些严重的错别字。引号的使用也不正确。修复该行并使用 bash 4.3.11(1) 进行测试
      【解决方案4】:

      你可以这样做:

      #!/bin/bash
      CommandResult="Interface    Chipset     Driver     mon0    Unknown      iwlwifi - [phy0]wlan0       Unknown     iwlwifi - [phy0]"
      InstanceId="mon0";
      count=`grep -o "$InstanceId" <<< "$CommandResult" | wc -l`
      echo "$InstanceId encountered "$count" times";
      

      上面会产生这样的输出:

      mon0 遇到 1 次

      上面可以很容易地扩展为将字符串作为输入:

      #!/bin/bash
      CommandResult=$1
      InstanceId="mon0";
      count=`grep -o "$InstanceId" <<< "$CommandResult" | wc -l`
      echo "$InstanceId encountered "$count" times";
      

      那么你可以这样称呼它:

      ./script.sh "Interface chipset mon0 mon0 unknown .   test"
      

      或者也许将另一个命令的输出作为参数发送:

      ./script.sh `cat file.txt`
      

      当然xargs 也可以:

      cat script.txt | xargs ./script.sh
      

      【讨论】:

        【解决方案5】:

        你可以使用:

        mon_num=$(airmon-ng | grep -Poc '\bmon\d+\b')
        echo here are $mon_num mon interfaces
        
        for m in $(airmon-ng | grep -Po '\bmon\d+\b')
        do
                #do something
                echo "this is $m"
        done
        

        对于airmon-ng 输出如:

        Interface   Chipset     Driver
        
        mon0        Unknown     iwlwifi - [phy0]
        mon1        Unknown     iwlwifi - [phy0]
        mon2        Unknown     iwlwifi - [phy0]
        wlan0       Unknown     iwlwifi - [phy0]
        

        将打印

        here are 3 mon interfaces
        this is mon0
        this is mon1
        this is mon2
        

        【讨论】:

          猜你喜欢
          • 2023-04-06
          • 2023-03-28
          • 1970-01-01
          • 1970-01-01
          • 2021-01-24
          • 2017-10-20
          • 2019-09-14
          相关资源
          最近更新 更多