【问题标题】:How to count the number of numbers/letters in file?如何计算文件中的数字/字母数量?
【发布时间】:2016-05-15 21:10:34
【问题描述】:

我尝试在 Bash 中计算文件中数字和字母的数量。 我知道我可以使用wc -c file 来计算字符数,但如何才能将其修复为仅字母和数字?

【问题讨论】:

    标签: linux bash shell wc


    【解决方案1】:

    这是一种完全避免管道的方法,只使用tr 和shell 的方法来给出变量的长度${#variable}

    $ cat file
    123 sdf
    231 (3)
    huh? 564
    242 wr =!
    $ NUMBERS=$(tr -dc '[:digit:]' < file)
    $ LETTERS=$(tr -dc '[:alpha:]' < file)
    $ ALNUM=$(tr -dc '[:alnum:]' < file)
    $ echo ${#NUMBERS} ${#LETTERS} ${#ALNUM}
    13 8 21
    

    【讨论】:

      【解决方案2】:

      要计算字母和数字的数量,您可以将grepwc 结合起来:

       grep -o [a-z] myfile | wc -c
       grep -o [0-9] myfile | wc -c
      

      只需稍作调整,您就可以对其进行修改以计算数字或字母单词或字母数字单词,

      grep -o [a-z]+ myfile | wc -c
      grep -o [0-9]+ myfile | wc -c
      grep -o [[:alnum:]]+ myfile | wc -c
      

      【讨论】:

      • 终端显示第一个和第二个示例的输出不正确,嗯?
      • 这会计算任何包含至少一个一个字母或数字字符的行的所有字符。
      • 将其设为grep -o 用于计算mixed line 111
      • 当您在当前目录中有一个名为 a7 的文件时,首先提到的 grep 会失败。总是引用 shell 元字符!
      【解决方案3】:

      您可以使用 sed 替换所有不属于您要查找的类型的字符,然后对结果的字符进行字数统计。

      # 1h;1!H will place all lines into the buffer that way you can replace
      # newline characters
      sed -n '1h;1!H;${;g;s/[^a-zA-Z]//g;p;}' myfile | wc -c
      
      It's easy enough to just do numbers as well.
      sed -n '1h;1!H;${;g;s/[^0-9]//g;p;}' myfile | wc -c
      
      Or why not both.
      sed -n '1h;1!H;${;g;s/[^0-9a-zA-Z]//g;p;}' myfile | wc -c
      

      【讨论】:

        【解决方案4】:

        有多种方法可以在 bash 中分析文本文件的 单词字符频率。利用 bash 内置的字符大小写过滤器(例如 [:upper:] 等),您可以深入了解文本文件中每种字符类型的每次出现频率。下面是一个简单的脚本,它从stdin 读取并提供正常的wc 输出作为第一行输出,然后输出upperlowerdigitspunct 和@987654328 的数量@。

        #!/bin/bash
        
        declare -i lines=0
        declare -i words=0
        declare -i chars=0
        declare -i upper=0
        declare -i lower=0
        declare -i digit=0
        declare -i punct=0
        
        oifs="$IFS"
        
        # Read line with new IFS, preserve whitespace
        while IFS=$'\n' read -r line; do
        
            # parse line into words with original IFS
            IFS=$oifs
            set -- $line
            IFS=$'\n'
        
            # Add up lines, words, chars, upper, lower, digit
            lines=$((lines + 1))
            words=$((words + $#))
            chars=$((chars + ${#line} + 1))
            for ((i = 0; i < ${#line}; i++)); do
                [[ ${line:$((i)):1} =~ [[:upper:]] ]] && ((upper++))
                [[ ${line:$((i)):1} =~ [[:lower:]] ]] && ((lower++))
                [[ ${line:$((i)):1} =~ [[:digit:]] ]] && ((digit++))
                [[ ${line:$((i)):1} =~ [[:punct:]] ]] && ((punct++))
            done
        done
        
        echo " $lines $words $chars $file"
        echo " upper: $upper,  lower: $lower,  digit: $digit,  punct: $punct,  \
        whitespace: $((chars-upper-lower-digit-punct))"
        

        测试输入

        $ cat dat/captnjackn.txt
        This is a tale
        Of Captain Jack Sparrow
        A Pirate So Brave
        On the Seven Seas.
        (along with 2357 other pirates)
        

        使用/输出示例

        $ bash wcount3.sh <dat/captnjackn.txt
         5 21 108
         upper: 12,  lower: 68,  digit: 4,  punct: 3,  whitespace: 21
        

        您可以自定义脚本以提供尽可能少或尽可能多的细节。如果您有任何问题,请告诉我。

        【讨论】:

          【解决方案5】:

          您可以使用tr 通过组合-c(补码)和-d(删除)标志来仅保留字母数字字符。从那里开始,这只是一些管道的问题:

          $ cat myfile.txr | tr -cd [:alnum:] | wc -c
          

          【讨论】:

          • cat myfile.txr | tr -cd [123456789] | wc -c那个例子对吗?
          • 无用的猫。如果有一个名为 m 的文件,则会失败。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-07-08
          • 1970-01-01
          相关资源
          最近更新 更多