我有一个像下面这样的字符串(nvram extract),由tinc VPN用来定义网络主机:
1<host1<host1.network.org<<0<10.10.10.0/24<<Ed25519PublicKey = 8dtRRgAaTbUNtPxW9U3nGn6U7uvfIPwRo1wnx7xMIUH<Subnet = 10.10.3.0/24>1<host2<host2.network.org<<0<10.10.9.0/24<<Ed25519PublicKey = irn48tqF2Em4rIG0ggBmpEfaVKtkl6DmGdSzTHMmVEI<>0<host3<host3.network.org<<0<10.10.11.0/24<<Ed25519PublicKey = wQt1sFwOsd1hnBaNGHq4JDyib22fOg1YqzOp0p08ZTD<>
我试图从上面提取:
host1.network.org
host2.network.org
host3.network.org
组成主机名和键,但输入字符串的结构是准确的。顺便说一句,终端节点也可以被定义为IP地址,所以我试图提取第二次出现的&#34;&lt;&#34;之间的内容。并且第一次出现&#34;&lt;&lt;&#;;由于这是多重匹配,因此在行开头或&#34;&gt;&#34;之后计算事件。字符。所以上面的内容可以理解如下:
1<host1<host1.network.org<<0<10.10.10.0/24<<Ed25519PublicKey = 8dtRRgAaTbUNtPxW9U3nGn6U7uvfIPwRo1wnx7xMIUH<Subnet = 10.10.3.0/24>
1<host2<host2.network.org<<0<10.10.9.0/24<<Ed25519PublicKey = irn48tqF2Em4rIG0ggBmpEfaVKtkl6DmGdSzTHMmVEI<>
0<host3<host3.network.org<<0<10.10.11.0/24<<Ed25519PublicKey = wQt1sFwOsd1hnBaNGHq4JDyib22fOg1YqzOp0p08ZTD<>
由于我需要在shell脚本中使用此信息,我想我需要将每个主机/ IP存储为数组的元素。
我使用了regexp在线编辑器,并设法计算出这个字符串:
^[0|1]<.*?(\<(.*?)\<<)|>[0|1]<.*?(\<(.*?)\<)
但是我跑了
grep -Eo '^[0|1]<.*?(\<(.*?)\<<)|>[0|1]<.*?(\<(.*?)\<)'
反对最初的刺激我得到了完整的字符串作为回报所以我一定做错了: - /
P.S。在buysbox上运行: `BusyBox v1.25.1(2017-05-21 14:11:58 CEST)多调用二进制文件。
用法:grep [-HhnlLoqvsriwFE] [-m N] [-A / B / C N] PATTERN / -e PATTERN ... / - f FILE [FILE] ...
在文件(或标准输入)中搜索PATTERN
-H Add 'filename:' prefix
-h Do not add 'filename:' prefix
-n Add 'line_no:' prefix
-l Show only names of files that match
-L Show only names of files that don't match
-c Show only count of matching lines
-o Show only the matching part of line
-q Quiet. Return 0 if PATTERN is found, 1 otherwise
-v Select non-matching lines
-s Suppress open and read errors
-r Recurse
-i Ignore case
-w Match whole words only
-x Match whole lines only
-F PATTERN is a literal (not regexp)
-E PATTERN is an extended regexp
-m N Match up to N times per file
-A N Print N lines of trailing context
-B N Print N lines of leading context
-C N Same as '-A N -B N'
-e PTRN Pattern to match
-f FILE Read pattern from file`
谢谢!
答案 0 :(得分:0)
您拥有的正则表达式基于捕获组,grep
只能获得完整匹配。此外,你使用-E
(POSIX ERE风味),而你的正则表达式实际上不兼容POSIX ERE,因为它包含这种风格不支持的惰性量词。
我认为您可以在<
和<
之间提取所有非<<
个字符,后跟一个数字,然后提取一个带有PCRE正则表达式的<
-P
}选项):
s='1<host1<host1.network.org<<0<10.10.10.0/24<<Ed25519PublicKey = 8dtRRgAaTbUNtPxW9U3nGn6U7uvfIPwRo1wnx7xMIUH<Subnet = 10.10.3.0/24>1<host2<host2.network.org<<0<10.10.9.0/24<<Ed25519PublicKey = irn48tqF2Em4rIG0ggBmpEfaVKtkl6DmGdSzTHMmVEI<>0<host3<host3.network.org<<0<10.10.11.0/24<<Ed25519PublicKey = wQt1sFwOsd1hnBaNGHq4JDyib22fOg1YqzOp0p08ZTD<>'
echo $s | grep -oP '(?<=<)[^<]+(?=<<[0-9]<)'
请参阅regex demo和grep
demo。
输出:
host1.network.org
host2.network.org
host3.network.org
此处,(?<=<)
是一个积极的外观,只检查当前位置左侧的<
存在,但不会将<
添加到匹配值{{1匹配除[^<]+
和<
之外的1 +字符(正向前瞻)需要(?=<<[0-9]<)
,然后是数字,然后是<<
,但同样不会添加这些字符到比赛。
如果<
中没有PCRE选项,请尝试使用某些字符替换所有不需要的文本,然后使用awk拆分,或使用grep
:
grep
答案 1 :(得分:0)
好的,我的评论没有回应,所以我会输入它作为答案。 <怎么样
grep -Eo '\w*[a-z]\w*(\.\w*[a-z]\w*)+'
它匹配至少完全限定名称的两部分,用点分隔。
{{1}}
产量
host1.network.org
host2.network.org
host3.network.org
(假设您的字符串是在stdin中输入的;)