Philip Kirkbride Asked: 2019-01-06 16:06:53 +0800 CST2019-01-06 16:06:53 +0800 CST 2019-01-06 16:06:53 +0800 CST 解析所有特定长度的字符串? 772 我已经导出了 10 年的电子邮件存档,非常大。 我想解析任何长度为 64 个字符的字符串的所有文本,以搜索比特币私钥。 如何解析字符中一定长度的字符串? text-processing files 4 个回答 Voted pizdelect 2019-01-06T17:10:45+08:002019-01-06T17:10:45+08:00 如果您要搜索十六进制形式的 256 位数字(范围内的 64 个字符0-9和A-F- 比特币私钥可能出现的格式之一),则应该这样做: egrep -aro '\<[A-F0-9]{64}\>' files and dirs ... 如果某些键是小写的,则添加-i选项或还包括范围。a-f 对于从具有指定长度的同一类中查找字符运行的一般问题,您最好使用 pcre 正则表达式,它可以与带有-P选项的 GNU grep 一起使用。例如,要从任何字符集中查找大写字母的运行,最小长度为 2,最大长度为 4,并且由非大写字母的字符分隔: echo ÁRVÍZtűrő tükörFÚRÓgép | LC_CTYPE=en_US.UTF-8 grep -Po '(?<!\p{Lu})\p{Lu}{2,4}(?!\p{Lu})' FÚRÓ 替换\p{Lu}为\p{Ll}小写字母、\S非空格等。完整列表请参见此处和此处。 (?<!...)并且(?!...)是消极的后瞻和前瞻零宽度断言;例如,当没有用and(?<!<)\w(?!>)括起来时,将匹配“单词”字符。零宽度断言可以由.<>\<vi(?<!\w)(?=\w) Fox 2019-01-06T16:42:50+08:002019-01-06T16:42:50+08:00 如果要从 中查找长度为 64 的所有单词/path/to/file,可以使用 tr -c '[:alnum:]' '\n' < /path/to/file | grep '^.\{64\}$' 这会将所有非字母数字字符替换为换行符,因此每个单词都在自己的行上。然后它过滤这个结果,只包含长度为 64 的单词。 Best Answer terdon 2019-01-06T16:47:50+08:002019-01-06T16:47:50+08:00 如果您有 GNU grep(Linux 上的默认设置),您可以执行以下操作: grep -Po '(^|\s)\S{64}(\s|$)' file 启用 Perl 兼容正-P则表达式,它为我们提供\b(字边界)\S(非空白)和{N}(精确找到 N 个字符),-o意思是“只打印行的匹配部分。然后,我们寻找非-长度正好为 64 个字符的空格,位于行首 ( ^) 或空格 ( 's) 之后,并且在行尾 ( $) 或以另一个空格字符结尾。 请注意,结果将在字符串的开头和结尾包含任何空白字符,因此如果您想进一步解析它,您可能希望使用它来代替: grep -Po '(^|\s)\K\S{64}(?=\s|$)' 这将查找空白字符或字符串的开头(\s|^),然后将其丢弃\K,然后查找 64 个非空白字符,然后查找((?=foo)称为“前瞻”并且不会包含在匹配中)空白字符,或行尾。 user232326 2019-01-06T17:50:15+08:002019-01-06T17:50:15+08:00 似乎 grep 是“搜索”字符串的正确工具。剩下要做的是用正则表达式定义这样的字符串。第一个问题是定义一个词的界限。它不像“空格”那么简单,不像a book, a lamp用作,单词分隔符,在同一个概念中,许多其他字符,甚至一行的开头或结尾都可以充当单词分隔符。GNU grep 中有一些单词分隔符: \<词开始。 \>词尾。 \b词界。 他们都假设一个词是一个[a-zA-Z0-9_]字符序列。如果这对你来说没问题,这个正则表达式可以工作: grep -o '\<.\{64\}\>' file 如果您可以使用扩展的正则表达式,则\可以减少: grep -oE '\<.{64}\>' file 它从“单词开头”(\<)、64 个({64})字符(.)到“单词结尾”(\>)进行选择,并仅打印匹配的(-o)部分。 但是,点 ( .) 将匹配任何字符,这可能太多了。 如果您想更严格地选择(十六进制数字),请使用: grep -oE '\<[0-9a-fA-F]{64}\>' file 这将允许小写或大写的十六进制数字。但是,如果您真的想严格一些,因为可能包含一些非 ASCII 字符,请使用: LC_ALL=C grep -oE '\<[0-9a-fA-F]{64}\>' file grep 的某些实现(如 grep -P)没有“单词开头”或“单词结尾”(as\<和\>),但具有“单词边界”(as \b): grep -oP '\b[0-9a-fA-F]{64}\b' file 有一些语言接受 POSIX 单词边界[[:<:]]和[[:>:]],但不接受 perl,并且仅来自 PCRE 8.34。 还有更多的“词界”。
如果您要搜索十六进制形式的 256 位数字(范围内的 64 个字符
0-9
和A-F
- 比特币私钥可能出现的格式之一),则应该这样做:如果某些键是小写的,则添加
-i
选项或还包括范围。a-f
对于从具有指定长度的同一类中查找字符运行的一般问题,您最好使用 pcre 正则表达式,它可以与带有
-P
选项的 GNU grep 一起使用。例如,要从任何字符集中查找大写字母的运行,最小长度为 2,最大长度为 4,并且由非大写字母的字符分隔:替换
\p{Lu}
为\p{Ll}
小写字母、\S
非空格等。完整列表请参见此处和此处。(?<!...)
并且(?!...)
是消极的后瞻和前瞻零宽度断言;例如,当没有用and(?<!<)\w(?!>)
括起来时,将匹配“单词”字符。零宽度断言可以由.<
>
\<
vi
(?<!\w)(?=\w)
如果要从 中查找长度为 64 的所有单词
/path/to/file
,可以使用这会将所有非字母数字字符替换为换行符,因此每个单词都在自己的行上。然后它过滤这个结果,只包含长度为 64 的单词。
如果您有 GNU
grep
(Linux 上的默认设置),您可以执行以下操作:启用 Perl 兼容正
-P
则表达式,它为我们提供\b
(字边界)\S
(非空白)和{N}
(精确找到 N 个字符),-o
意思是“只打印行的匹配部分。然后,我们寻找非-长度正好为 64 个字符的空格,位于行首 (^
) 或空格 ('s
) 之后,并且在行尾 ($
) 或以另一个空格字符结尾。请注意,结果将在字符串的开头和结尾包含任何空白字符,因此如果您想进一步解析它,您可能希望使用它来代替:
这将查找空白字符或字符串的开头
(\s|^)
,然后将其丢弃\K
,然后查找 64 个非空白字符,然后查找((?=foo)
称为“前瞻”并且不会包含在匹配中)空白字符,或行尾。似乎 grep 是“搜索”字符串的正确工具。剩下要做的是用正则表达式定义这样的字符串。第一个问题是定义一个词的界限。它不像“空格”那么简单,不像
a book, a lamp
用作,
单词分隔符,在同一个概念中,许多其他字符,甚至一行的开头或结尾都可以充当单词分隔符。GNU grep 中有一些单词分隔符:\<
词开始。\>
词尾。\b
词界。他们都假设一个词是一个
[a-zA-Z0-9_]
字符序列。如果这对你来说没问题,这个正则表达式可以工作:如果您可以使用扩展的正则表达式,则
\
可以减少:它从“单词开头”(
\<
)、64 个({64}
)字符(.
)到“单词结尾”(\>
)进行选择,并仅打印匹配的(-o
)部分。但是,点 (
.
) 将匹配任何字符,这可能太多了。如果您想更严格地选择(十六进制数字),请使用:
这将允许小写或大写的十六进制数字。但是,如果您真的想严格一些,因为可能包含一些非 ASCII 字符,请使用:
grep 的某些实现(如 grep -P)没有“单词开头”或“单词结尾”(as
\<
和\>
),但具有“单词边界”(as\b
):有一些语言接受 POSIX 单词边界
[[:<:]]
和[[:>:]]
,但不接受 perl,并且仅来自 PCRE 8.34。还有更多的“词界”。