我这里有grep
次操作,可以从ifconfig
的输出中为您提供外部 IP:
ipa=$(ifconfig | grep -Po "inet addr:\K[^\s]+" | grep -v "^127")
我希望只使用一个grep
,所以我尝试了以下内容,但部分成功:
ipa=$(ifconfig | grep -Po "inet addr:\K[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?")
部分成功,因为它还带来了空间加上内部IP ,出于某种原因:
MY_IP_ADDRESS 127.0.0.1
为什么会这样?我的意思是,为什么还添加了空间+环回,以及如何在仍然使用单个grep
时可以采取哪些措施来防止这种情况?环回甚至不是ifconfig
输出的相关行的一部分。
答案 0 :(得分:4)
鉴于您已经在使用grep -P
,您只需添加一个否定断言:
ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)\d{1,3}.\d{1,3}\.\d{1,3}\.\d{1,3}')
原始问题的正则表达式(因此编辑过)也会在点之间接受零数字;我也修复了这个问题,并简化了结果,希望略微提高易读性。
\K
是Perl的一项创新,它表示如果你匹配到这里,就忘记了到达这一点的文本"这意味着inet addr:
上的匹配不会包含在"匹配的文字中#34;由grep -o
打印。
表达式(?!127\.)
是一个负前瞻断言。简而言之,它说"如果这个正则表达式现在匹配,那么不匹配"。换句话说,正则表达式引擎会暂停一下,记下文本中的位置,然后向前看"并尝试匹配127\.
。如果成功,它会放弃尝试匹配此时,并继续尝试在字符串中的稍后点匹配整个表达式(因此,如果要在以后找到第二次出现inet addr:
在同一条线上,你仍然可以从那里得到一个匹配。)
最后,我将引用切换为单引号。它在这里并不重要,但我建议在所有正则表达式unless you specifically require the shell to perform variable replacements in the regex周围使用单引号。
至于你所看到的内容,输出中确实没有空间。 grep
输出两行,因为它找到两个匹配(当然我们现在使用负前瞻来防止;但是如果你配置了多个接口,你仍然可以获得多个结果)。如果您看到空格,那是因为您在回显时没有使用双引号,例如echo "$ipa"
。
如评论中所述,如果获得bash: !127: event not found
,则需要set +H
或将命令放在脚本中;或者,使用我在上一段中推荐的单引号。除非您沉迷于旧版Csh-style history management features in Bash(并且认真地了,现在是谁?),我建议您通过将set +H
命令放在.bash_profile
或类似内容中来永久更改此更改。
你可以重构你的正则表达式,使它更紧凑,但可能稍微不那么清晰:
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地址。
根据您的需要,您仍然可以在前瞻中添加更多要阻止的内容。为了防止它也匹配内部网络,比如
(?!127\.|10\.|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168\.)
会阻止在所有IANA保留的专用网络块中提取地址,包括环回。
答案 1 :(得分:3)
使用ifconfig
,ip
,dig
或我个人最喜欢的myip
,有几种方法可以实现这一目标。此外,还有更多方法可以优化您的正则表达式,其中许多可能已经在previous question的评论中看到过。
但是,为了回答字面而不重写命令或强加个人偏好,只需指定界面即可实现排除环回地址所需的结果做想要获取ifconfig
的第一个参数。默认情况下(即没有args),ifconfig
会显示所有当前活动界面的状态。
这样的事情应该足够了:
# Replace "eth0" with the appropriately configured static inet address' interface
# ... is your `grep` pipe
ifconfig "eth0" ...
man ifconfig
如果没有给出参数,ifconfig将显示当前活动接口的状态。
答案 2 :(得分:1)
正如Triplee在评论中指出的那样(Triplee的回答应该被推翻):
init addr:
前兆的IP。echo $ipa
代替"echo "$ipa"
,我们添加了空格。鉴于我也获得了环回,因为正则表达式也匹配它(我在开始时没有注意到它,因为它接近ifconfig
输出的结尾,我做的是使用{{ 1}} grep
参数。这个参数使-m1
只带来第一个匹配(外部IP确实更早,先发现),所以结束命令是:
grep
然而,正如Triplee的评论一样,原则上假设第一场比赛是外部IP而不是环回--- ipa=$(ifconfig | grep -Po -m1 "inet addr:\K[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?\.[0-9]{1,3}?")
明天可能会改变,将环回作为第一场,这是有问题的,所以应该使用Triplee的这个单一ifconfig
解决方案,涉及否定断言:
grep
或者Triplee的一个较短的替代方案,它通过执行ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)\d{1,3}.\d{1,3}\.\d{1,3}\.\d{1,3}')
在交互式shell中启用历史扩展防护:
set +H
注意:如果出现错误,则需要执行ipa=$(ifconfig | grep -Po 'inet addr:\K(?!127\.)[.\d]+')
。尽管可以使用set +H
撤销此状态,但保持此状态没有问题。
无论哪种方式,另一种最小的方法是我在问题中发表的原始2 set -H
方法:
grep
答案 3 :(得分:0)
排除以127.
开头的地址:
ifconfig | grep -Po '\binet addr:\K(?!127\.)\S+'
排除lo
适配器:
ifconfig | perl -nle'BEGIN { $/="" } next if /^lo\b/; print for /\binet addr:(\S+)/g'
只是一个特定的适配器:
ifconfig eth1 | grep -Po '\binet addr:\K\S+'
以太网适配器的第一个地址,只有一个:
ifconfig | perl -nle'BEGIN { $/="" } if (/^eth.*?\binet addr:(\S+)/s) { print $1; exit; }'