【问题标题】:Grep regular expression for digits in character string of variable length可变长度字符串中数字的grep正则表达式
【发布时间】:2009-12-07 21:57:51
【问题描述】:

我需要一些方法来查找包含任意字符和数字组合但只有 4 个数字和至少一个字符的单词。

示例:

a1a1a1a1        // Match
1234            // NO match (no characters)
a1a1a1a1a1      // NO match
ab2b2           // NO match
cd12            // NO match
z9989           // Match
1ab26a9         // Match
1ab1c1          // NO match
12345           // NO match
24              // NO match
a2b2c2d2        // Match
ab11cd22dd33    // NO match

【问题讨论】:

  • 为什么不是“1234”?它正好有 4 位数字。您需要更准确地了解您的要求。
  • 我的意思是字符和数字的任意组合(两个字符数字) cat test ab2b2 cd12 z9989 1ab26a9 1ab1c1 12345 24 a2b2c2d2 ab11cd22dd33 有效输出应该是 a2b2c2d2 z9989 1ab26a9

标签: regex shell grep


【解决方案1】:

grep:

grep -iE '^([a-z]*[0-9]){4}[a-z]*$' | grep -vE '^[0-9]{4}$'

使用 Perl 以一种模式进行:

perl -ne 'print if /^(?!\d{4}$)([^\W\d_]*\d){4}[^\W\d_]*$/'

时髦的[^\W\d_] 字符类是[A-Za-z] 拼写的国际化方式:它可以捕获所有字母,而不仅仅是英文字母。

【讨论】:

    【解决方案2】:

    我不确定您可能接受的所有其他输入(即ax12ax12ax12ax12 是否有效?),但这将根据您发布的内容起作用:

    %> grep -P "^(?:\w\d){4}$" fileWithInput
    

    【讨论】:

    • 在某些情况下,您可能希望使用\b 字边界而不是 BOL (^) 和 EOL ($)。
    • @Dennis。好点子。我正在编写它以匹配他提供的输入,但如果每行有多个单词,那么是的,我应该使用 \b 代替 ^ 和 $。
    【解决方案3】:

    要匹配 grep 中的数字,您可以使用 [0-9]。要匹配除数字以外的任何内容,您可以使用 [^0-9]。由于它可以是任意数量的字符,或者没有字符,因此您添加一个“*”(前面的任意数量)。所以你想要的是合乎逻辑的

    (anything not a digit or nothing)* (any single digit) (anything not a digit or nothing)* ....

    直到您有 4 个“任意一位数”组。即 [^0-9]*[0-9]...

    我发现使用 grep 长模式,尤其是需要转义的长串特殊字符时,最好慢慢建立,这样你就确定你明白发生了什么。例如,

    #this will highlight your matches, and make it easier to understand
    alias grep='grep --color=auto'
    echo 'a1b2' | grep '[0-9]' 
    

    会告诉你它是如何匹配的。一旦理解了每个部分,您就可以扩展该模式。

    【讨论】:

      【解决方案4】:

      如果你不介意使用小 shell,你可以这样做:

      echo "a1a1a1a1" |grep -o '[0-9]'|wc -l
      

      这将显示在字符串中找到的位数。如果您愿意,您可以测试给定数量的匹配项:

      max_match=4
      [ "$(echo "a1da4a3aaa4a4" | grep -o '[0-9]'|wc -l)" -le $max_match ] || echo "too many digits."
      

      【讨论】:

        【解决方案5】:

        假设您只需要 ASCII,并且您只能访问 grep 的(相当原始的)正则表达式结构,以下应该非常接近:

        grep ^[a-zA-Z]*[0-9][a-zA-Z]*[a-zA-Z]*[0-9][a-zA-Z]*[a-zA-Z]*[0-9][a-zA-Z]*[a-zA-Z]*[0-9][a-zA-Z]*$ | grep [a-zA-Z]
        

        【讨论】:

          【解决方案6】:

          你可以试试

          [^0-9]*[0-9][^0-9]*[0-9][^0-9]*[0-9][^0-9]*[0-9][^0-9]*
          

          但这将匹配 1234。为什么不符合您的条件?

          【讨论】:

            【解决方案7】:

            正则表达式是:

            ([A-Za-z]\d){4}
            
            • [A-Za-z] - 用于字符类
            • \d - 代表数字
            • 您将它们包装在 () 中以将它们分组,指示格式字符后跟数字
            • {4} - 表示必须是4次重复

            【讨论】:

              【解决方案8】:

              你可以使用普通的shell脚本,不需要复杂的正则表达式。

              var=a1a1a1a1
              alldigits=${var//[^0-9]/}
              allletters=${var//[0-9]/}
              case "${#alldigits}" in
                 4)
                  if [ "${#allletters}" -gt 0 ];then
                      echo "ok: 4 digits and letters: $var"
                  else
                      echo "Invalid: all numbers and exactly 4: $var"
                  fi
                  ;;
                 *) echo "Invalid: $var";;
              esac
              

              【讨论】:

              • 实际上是我写的脚本:) #!/bin/bash echo "$@" |tr -s " " "\n"s >> 排序 cat 排序 |while read tostr do l=$ (echo $tostr|tr -d "\n"|wc -c) temp=$(echo $tostr|tr -d a-z|tr -d "\n"|wc -c) if [ $temp -eq 4 ] ;then if [ $l -gt 4 ];then printf "%s " "$tostr" fi fi done echo
              【解决方案9】:

              感谢您的回答 最后我写了一些脚本,它运行完美: . /P ab2b2 cd12 z9989 1ab26a9 1ab1c1 1234 24 a2b2c2d2

              #!/bin/bash
              echo "$@" |tr -s " " "\n"s >> sorting
              cat sorting | while read tostr
              do
                l=$(echo $tostr|tr -d "\n"|wc -c)
                temp=$(echo $tostr|tr -d a-z|tr -d "\n" | wc -c)
              
                if [ $temp -eq 4 ]; then
                  if [ $l -gt 4 ]; then
                    printf "%s " "$tostr"
                  fi
                fi
              done
              echo
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2016-11-15
                • 1970-01-01
                • 2018-07-11
                • 2014-10-22
                • 1970-01-01
                • 1970-01-01
                • 2023-03-15
                相关资源
                最近更新 更多