AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 442349
Accepted
Eduardo Lucio
Eduardo Lucio
Asked: 2018-05-08 07:10:52 +0800 CST2018-05-08 07:10:52 +0800 CST 2018-05-08 07:10:52 +0800 CST

计算字符串中子字符串出现的次数

  • 772

如何使用 Bash 计算字符串中子字符串的出现次数?

例子:

我想知道这个子字符串多少次:

Bluetooth
         Soft blocked: no
         Hard blocked: no

...出现在此字符串中...

0: asus-wlan: Wireless LAN
         Soft blocked: no
         Hard blocked: no
1: asus-bluetooth: Bluetooth
         Soft blocked: no
         Hard blocked: no
2: phy0: Wireless LAN
         Soft blocked: no
         Hard blocked: no
113: hci0: Bluetooth
         Soft blocked: no
         Hard blocked: no

注意 I:我已经尝试了几种使用 sed、grep、awk 的方法......当我们有带空格和多行的字符串时,似乎没有任何效果。

注意 II:我是 Linux 用户,我正在尝试一种解决方案,该解决方案不涉及安装通常在 Linux 发行版中找到的应用程序/工具之外的应用程序/工具。


重要的:

我想要类似下面的假设示例。在这种情况下,我们使用两个Shell 变量 (Bash)。

例子:

STRING="0: asus-wlan: Wireless LAN
         Soft blocked: no
         Hard blocked: no
1: asus-bluetooth: Bluetooth
         Soft blocked: no
         Hard blocked: no
2: phy0: Wireless LAN
         Soft blocked: no
         Hard blocked: no
113: hci0: Bluetooth
         Soft blocked: no
         Hard blocked: no"

SUB_STRING="Bluetooth
         Soft blocked: no
         Hard blocked: no"

awk -v RS='\0' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"

注意:我们使用 awk 只是为了说明!

bash shell-script
  • 6 6 个回答
  • 12785 Views

6 个回答

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2018-05-08T07:53:30+08:002018-05-08T07:53:30+08:00

    与perl:

    printf '%s' "$SUB_STRING" |
      perl -l -0777 -ne '
        BEGIN{$sub = <STDIN>}
        @matches = m/\Q$sub\E/g;
        print scalar @matches' <(printf '%s' "$STRING")
    

    独自一人,bash你总是可以做类似的事情:

    s=${STRING//"$SUB_STRING"}
    echo "$(((${#STRING} - ${#s}) / ${#SUB_STRING}))"
    

    即$scontains $STRING,其中所有出现的$SUB_STRING都被删除。$SUB_STRING我们通过计算 和 之间的字符数的差异并除以自身的长度来找出被删除$STRING的$ss$SUB_STRING的数量。

    POSIXly,您可以执行以下操作:

    s=$STRING count=0
    until
      t=${s#*"$SUB_STRING"}
      [ "$t" = "$s" ]
    do
      count=$((count + 1))
      s=$t
    done
    echo "$count"
    
    • 8
  2. Rakesh Sharma
    2018-05-08T12:38:27+08:002018-05-08T12:38:27+08:00

    使用字符串处理函数,我们可以使用 Perl 进行如下操作:

     printf '%s\n' "$STRING" |
     perl -nse '
          $_ .= join "", <>;
          $k++ while ++($p = index($_, $s, $p));
          print $k, "\n" ;
     '    --     -s="$SUB_STRING" 
    

    解释:

    ° load up the whole string in $_
    
    °  index function will return the position of a substring in a string OTW returns -1
    
    ° progressively match the substring and use the position found as the starting position for the next search. 
    
    °  all this while increment the counter $k depicting substring found. 
    

    下面列出了一些其他方法:

    啜饮字符串并使用正则表达式。

    printf '%s\n' "$STRING" |
    perl -slp -0777e '
            $_ = () = /$s/g;
     ' -- -s="$s" 
    

    ° 将字符串插入 $_ 变量中。

    ° 使用 -s 选项将子字符串从命令行传递给 perl。

    ° 现在在 $_ 上执行匹配,并在列表上下文中为您获取匹配项,然后在标量上下文中获取匹配项的数量。

    ° -p 选项将自动打印 $_ 中的内容。

    使用 sed 工具的方法:

     esc_s=$(printf '%s\n' "$SUB_STRING" |\
     sed -e 's:[][\/.^$*]:\\&:g' -e 'H;1h;$!d;g;s/\n/\\n/g')
    
     printf '%s\n' "$STRING" |
     sed -ne '
             $!{N;s/^/\n/;D;}
             /'"$esc_s"'/{
                   x;p;x
                   s///;s/^/\n/;D
             }
     ' | wc -l
    

    ° 作为准备步骤,我们继续将所有充当元字符的字符转义到子字符串中 s/// 语句的左侧,如果不这样做将导致 sed 崩溃。

    ° 现在我们将整个字符串吞入模式空间。

    ° 然后我们继续打印一个空行,保持空间是一个很好的候选,并从模式空间中取出子字符串。

    ° 冲洗……泡沫……只要存在子串就重复。

    ° 然后将空行通过管道传输到 wc 工具,该工具将为我们提供行数 = 找到子字符串的次数。

    这是外壳版本:

     e=$STRING  N=0
     while 
         e=$(expr " $e" : " \(.*\)$SUB_STRING")
         case $e in "" ) break ;; esac
      do
               N=$(expr "$N" + 1)
      done
      echo "$N"
    
    • 3
  3. Sapphire_Brick
    2020-11-08T19:15:55+08:002020-11-08T19:15:55+08:00

    如果子字符串不包含换行符:

    echo -n STRING | grep -Fo SUBSTRING | wc -l
    
    • 3
  4. Katu
    2018-05-09T06:19:46+08:002018-05-09T06:19:46+08:00

    你可以在这个问题中使用 Python

    python -c 'print "abcdabcva".count("ab")'
    

    或者,如果您正在使用 shell 变量:

    python -c 'print("""'"$STRING"'""".count("""'"$SUB_STRING"'"""))'
    

    在你的情况下:

    python -c 'print """0: asus-wlan: Wireless LAN
                       Soft blocked: no
                       Hard blocked: no
              1: asus-bluetooth: Bluetooth
                       Soft blocked: no
                       Hard blocked: no
              2: phy0: Wireless LAN
                       Soft blocked: no
                       Hard blocked: no
              113: hci0: Bluetooth
                       Soft blocked: no
                       Hard blocked: no""".count("""Bluetooth
                       Soft blocked: no
                       Hard blocked: no""")'
    
    • 2
  5. MiniMax
    2018-05-09T12:40:31+08:002018-05-09T12:40:31+08:00
    gawk '
    END { print NR - 1 }
    ' RS='Bluetooth
             Soft blocked: no
             Hard blocked: no' input.txt
    

    解释

    RS- 输入记录分隔符,默认为换行符。将其设置为所需的字符串,awk并将所有文本拆分为记录,使用此字符串作为分隔符。然后,它只剩下打印节中减去的记录1数END。

    使用变量:

    #!/bin/bash
    
    STRING='0: asus-wlan: Wireless LAN
             Soft blocked: no
             Hard blocked: no
    1: asus-bluetooth: Bluetooth
             Soft blocked: no
             Hard blocked: no
    2: phy0: Wireless LAN
             Soft blocked: no
             Hard blocked: no
    113: hci0: Bluetooth
             Soft blocked: no
             Hard blocked: no'
    
    SUB_STRING='Bluetooth
             Soft blocked: no
             Hard blocked: no'
    
    gawk 'END { print NR - 1 }' RS="$SUB_STRING" <<< "$STRING"
    
    • 2
  6. JJoao
    2018-05-08T22:03:46+08:002018-05-08T22:03:46+08:00

    如果你有 gnugrep,你可以运行一些类似的东西

    grep -zPio 'Bluetooth\s+Soft blocked: no\s+Hard blocked: no' ex.txt | grep -zc .

    • 1

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve