脚本:匹配和删除具有特定模式

时间:2017-05-20 15:40:18

标签: python bash awk sed grep

我正在尝试创建一个主词表,以测试我实验室中特定类型的路由器。我已经知道密码遵循的具体模式。我使用带有紧缩的字符集[A-F 0-9]创建了第一个wordlist(" raw_wordlist.txt")文件,

crunch  8 8 ABCDEF0123456789 -d 3 -o raw_wordlist.txt

女巫导致 4289986800 行文件名为" raw_wordlist.txt"。

现在我正在尝试进一步缩小fiewer行的词表。

这是一个片段:

193B068D
B9AB0685
B9AB068F
A9AAA69A
B98B069B
B9AB069C
B9AB069D
B9A2069E
B9AB069F

这是我想要实现的目标。

  • 删除以3个数字字符开头的所有行(如193B068D中所示)
  • 删除所有以3个数字字符结尾的行(如B9AB0685中所述)
  • 删除包含4个以上数值的所有行(如B98B069B或B9A2069E)
  • 删除包含4个以上相同字符值[A-F]的所有行(如A9AAA69A)

目前没有选项可以自动执行此操作,因此我唯一的选择是首先创建一个基本词表,然后使用脚本缩小范围。

我尝试过像

这样的解决方案
sed -e '/^[0-9]{3}/d' -e '/[0-9]{3}$/d' raw_wordlist.txt > hexwordlist.txt

女巫可以解决领先和拖尾数字问题,但我仍然要弄清楚如何基于字符数来消除。

我不知道如何使用sed或grep或awk,或者使用pypthon来实现它?任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:1)

让我们从 sed 解决方案开始,使用 BRE (基本的正则表达式):

sed '/^[0-9]\{3\}\|[0-9]\{3\}$\|[0-9].*[0-9].*[0-9].*[0-9].*[0-9].*\|\([A-F]\).*\1.*\1.*\1.*\1.*/d' file

输出(对于您当前的输入片段):

B9AB068F
B9AB069C
B9AB069D
B9AB069F
  • 整个表达式是一个替代组

  • ^[0-9]{3} - 匹配以3位开头的条目

  • [0-9]$ - 匹配以3位数结尾的条目

  • [0-9].*[0-9].*[0-9].*[0-9].*[0-9].* - 匹配包含至少5位数(超过4位)的条目

  • ([A-F]).*\1.*\1.*\1.*\1.* - 匹配包含至少5个相同的条目 字母[A-F](超过4)

  • d - sed 子命令以删除匹配的行

替代 sed 方法(使用 ERE )如下所示:

sed -E '/^[0-9]{3}|[0-9]{3}$|([0-9].*){5}|([A-F])(.*\2){4}/d' file

答案 1 :(得分:0)

添加不依赖于正则表达式的解决方案。通过向matchers列表中添加新功能,可以相当容易地扩展。

#!/usr/bin/python

import collections

inputcontent = """193B068D
B9AB0685
B9AB068F
A9AAA69A
B98B069B
B9AB069C
B9AB069D
B9A2069E
B9AB069F
""".strip()

# Read inputcontent from standard input if you want, otherwise just copy into
# this string.

def starts_with_3_numeric(s):
    return all(c in "0123456789" for c in s[:3])

def ends_with_3_numeric(s):
    return all(c in "0123456789" for c in s[-3:])

def contains_4_numeric(s):
    return len([c for c in s if c in "0123456789"]) > 4

def contains_more_than_4_equal_chars(s):
    count = collections.Counter(s)
    return max(count[c] for c in s) > 4

matchers = [
    starts_with_3_numeric,
    ends_with_3_numeric,
    contains_4_numeric,
    contains_more_than_4_equal_chars,
]

filtered = [line.strip()
            for line in inputcontent.splitlines()
            if not any(matcher(line.strip()) for matcher in matchers)]

for outline in filtered:
    print outline

答案 2 :(得分:0)

FWIW在这里你是如何用GNU awk为patsplit()(或FPAT)做的:

$ cat tst.awk
/^[0-9]{3}|[0-9]{3]+$/ { next }
gsub(/[0-9]/,"&") > 4  { next }
{
    delete cnt
    patsplit($0,tgt,/[A-F]/)
    for (i in tgt) {
        if ( ++cnt[tgt[i]] > 4 ) {
            next
        }
    }
}
{ print }

$ awk -f tst.awk file
B9AB068F
B9AB069C
B9AB069D
B9AB069F

它需要比sed更多的代码,因为与sed不同,awk不支持regexp中的反向引用。