Regex grep外部IP还带回了内部IP - 为什么? [英] Regex grep external IP brings back internal IP as well - why?

查看:151
本文介绍了Regex grep外部IP还带回了内部IP - 为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里有 grep 操作,它为您提供 ifconfig 外部 IP $ c>:

I have this grep operation here that gives you the external IP from the output of ifconfig:

ipa=$(ifconfig | grep -Po "inet addr:\K[^\s]+" | grep -v "^127")

我只想使用一个 grep ,所以我尝试了以下,部分成功:

I desire to use only one grep, so I tried the following, which was partly successful:

ipa=$(ifconfig | grep -Po "inet addr:\K[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?")

部分成功因为它还带来了空间加上内部IP ,出于某种原因:

It is partly successful because it also brings a space plus the internal IP, for some reason:


MY_IP_ADDRESS 127.0.0.1

MY_IP_ADDRESS 127.0.0.1

为什么会发生这种情况?我的意思是,为什么还添加了空间+环回,以及在使用单个 grep 时可以采取哪些措施来防止这种情况,如果在所有?环回甚至不是 ifconfig 输出的相关行的一部分。

Why is this happening? I mean, why are the space + loopback added as well, and what can be done to prevent that while still using a single grep, if at all? The loopback isn't even part of the relevant line of the ifconfig output.

推荐答案

鉴于您已经在使用 grep -P ,您只需添加否定断言:

Given that you are already using grep -P, you can simply add a negative assertion:

ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)\d{1,3}.\d{1,3}\.\d{1,3}\.\d{1,3}')

原始问题的正则表达式(因此编辑)也会在点之间接受零数字;我也修复了这个问题,并简化了结果,希望略微提高易读性。

Your original question's regex (hence edited) would also accept zero numbers between the dots; I fixed that as well and simplified the result for hopefully slightly improved legibility.

\K 是一个Perl创新说如果你匹配到这里,忘记到达这一点的文本,这意味着 inet addr:上的匹配将不会包含在匹配的文本中由打印grep -o

The \K is a Perl innovation which says "if you match through to here, forget the text which got to this point" which means the match on inet addr: will not be included in the "matched text" printed by grep -o.

表达式(?!127 \。 )是一个负前瞻断言。简而言之,它说如果这个正则表达式现在匹配,那么匹配。换句话说,正则表达式引擎会暂停一下,记下文本中的位置,并向前查看并尝试匹配 127 \。。如果成功,它会在此时放弃尝试匹配,并继续尝试在字符串中的稍后点匹配整个表达式(因此,如果要查找第二次出现的 inet addr :稍后在同一行,你仍然可以从那里得到一个匹配。)

The expression (?!127\.) is a negative lookahead assertion. In brief, it says "if this regex would match now, this is not a match". In other words, the regex engine takes a brief pause, takes a note of where it is in the text, and "peeks ahead" and attempts to match 127\.. If that succeeds, it gives up on attempting to match at this point, and proceeds to attempt to match the entire expression at a later point in the string (so if it were to find a second occurrence of inet addr: later on in the same line, you could still get a match from there).

最后,我将引用切换为单引号。这里并不重要,但我推荐所有正则表达式的单引号除非你特别要求shell在正则表达式中执行变量替换或类似的东西。

Finally, I switched the quoting to single quotes. It doesn't really matter a lot here, but I recommend single quotes around all regular expressions unless you specifically require the shell to perform variable replacements in the regex or something like that.

至于解释你看到的内容,没有输出中的空间真的。 grep 输出两行,因为它找到了两个匹配项(当然我们现在使用负前瞻预防;但如果你配置了多个接口,你仍然可以得到多个结果)。如果您看到空格,那是因为您在回显时没有使用双引号,如 echo$ ipa

As for explaining what you saw, there is no space in the output really. The grep outputs two lines because it finds two matches (which of course we now prevent with the negative lookahead; but if you have multiple interfaces configured, you could still get more than one result). If you are seeing a space, that's because you didn't use double quotes when echoing, as in echo "$ipa".

如评论中所述,如果你得到 bash:!127:找不到事件,你需要设置+ H 或将命令放在脚本中;或者,使用我在上一段中推荐的单引号。除非您沉迷于传统的 Csh风格的历史记录管理功能Bash (严肃地说,现在是谁?),我建议您通过在<$ c $中添加命令 set + H 来永久更改此更改c> .bash_profile 或类似。

As noted in comments, if you get bash: !127: event not found, you need to set +H or put the commands in a script; or, use single quotes like I recommend in the previous paragraph. Unless you are addicted to the legacy Csh-style history management features in Bash (and seriously, who is, these days?), I recommend you make this change permanent by putting the command set +H in your .bash_profile or similar.

你可以重构你的正则表达式,使其更紧凑,但可能稍微不易清晰:

You could refactor your regex to make it more compact but perhaps slightly less legible:

ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)\d{1,3}(?:.\d{1,3}){3}')

更简单的方法是:

ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)[.\d]+')

请注意相同的 \K (?!127 \。)模式,还有新的 [。\d] + ,它取代了 \\d {1,3} .\d {1,3} \.\d {1,3} \.\d {1,3})图案。这稍微不那么精确,但对于这种情况可能已经足够好了。如果您的输入来自 ifconfig ,并且您已经看到 inet addr:路标,则匹配尽可能多的数字和点可能应该总是得到你正在寻找的IP地址。

Note the same \K and (?!127\.) patterns, but also the new [.\d]+ which replaces the \d{1,3}.\d{1,3}\.\d{1,3}\.\d{1,3}') pattern. This is slightly less precise, but probably good enough for this scenario. If your input comes from ifconfig and you have already seen the inet addr: signpost, matching as many digits and dots as possible should always get you the IP address you are looking for.

根据你的需要,你仍然可以在前瞻中添加更多东西。为了防止它也匹配内部网络,例如

Depending on what you need this for, you could still add more things to block in the lookahead. To prevent it from also matching internal networks, something like

(?!127\.|10\.|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168\.)

会阻止在所有IANA保留的专用网络块中提取地址,包括环回。

would prevent extraction of addresses in all IANA-reserved private network blocks, including loopback.

这篇关于Regex grep外部IP还带回了内部IP - 为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆