2016-04-05 70 views
6

这是一个简单的脚本运行子进程,它从终端的ifconfig命令输出中检索IP。 我注意到subprocess.check_output()总是返回一个值\npython subprocess output without n

我希望得到一个返回值没有\n。 这怎么办?

$ python 
>>> import subprocess 
>>> subprocess.check_output("ifconfig en0 | awk '{ print $2}' | grep -E -o '([0-9]{1,3}[\.]){3}[0-9]{1,3}'", shell=True) 
'129.194.246.245\n' 
+2

'echo'补充说,新行.. –

+0

没有不仅仅。如果我运行'subprocess.check_output(“ifconfig en0 | awk'{print $ 2}'| grep -E -o'([0-9] {1,3} [\。]){3} [0-9] {1,3}'“,shell = True)''它在bash mac OS X上检索我的IP地址,返回行也存在 – Jupiter

+0

echo -n没有echo换行符。或者在子进程行末尾添加.strip() – Benjamin

回答

15

对于一个通用的方法:

subprocess.check_output("echo hello world", shell=True).strip() 
+0

这不回答*为什么*在输出中有一个换行符;无论是“echo”还是“grep”输出。提示:它不是'check_output()'添加它。 –

+4

问题不是为什么,而是如何删除它:-D我想答案是,命令行二进制文件在其输出结尾处添加一个新行,以便在(在不同的行上)有一个很好的shell提示符。 – Benjamin

+0

我想我们只是在解释这个问题上有所不同。 *我注意到'subprocess.check_output()'总是返回一个带'\ n' *的值。 OP改变了这个问题,即使使用'grep -o',他们仍然得到这个换行符(就好像证明指向回显的答案,因为换行符的来源是错误的)。 –

1

subprocess.check_output()添加一个换行符。 echo呢。您可以使用-n开关可抑制换行,但你必须使用内置的实现壳避免(因此使用/bin/echo):

>>> import subprocess 
>>> subprocess.check_output('/bin/echo -n hello world', shell=True) 
'hello world' 

如果使用echo -n相反,你可以得到字符串'-n hello world\n' ,因为并非所有的sh实现都支持-n交换机支持echo(例如OS X)。

你总是可以使用str.rstrip()str.strip()去除空白,当然,但不怪subprocess这里:

subprocess.check_output("ifconfig en0 | awk '{ print $2}' | grep -E -o '([0-9]{1,3}[\.]){3}[0-9]{1,3}'", shell=True) 

>>> subprocess.check_output('echo hello world', shell=True).rstrip('\n') 
'hello world' 

你的问题更新使用awkgrep增添了更复杂的例子

这里grep添加(最终)换行符。 grep -o可能会打印只是的匹配文字,但仍会添加一个换行符来分隔匹配。看到grep manual

-o
--only匹配

仅打印匹配的(非空)的匹配线的部分,与上一个单独的输出线每一个这样的部分。

强调我的。

您可以在末尾添加tr -d '\n'从你管的输出删除任何换行符:

>>> subprocess.check_output(
...  "ifconfig en0 | awk '{ print $2}' | " 
...  "grep -E -o '([0-9]{1,3}[\.]){3}[0-9]{1,3}' | " 
...  "tr -d '\n'", shell=True) 
'172.17.174.160' 
+0

我不认为这是一个关于回声的问题,“rstrip”是OP需要的东西 –

+1

@PadraicCunningham:*依赖*。重要的是要指出'check_process'添加这个换行符的假设是不正确的。 –

+1

@PadraicCunningham:考虑到问题的改变,OP几乎肯定仍然声称新行是由'check_output'添加的。你可以用'str.rstrip()'去除换行符在这里并不重要。 –

0

可以str.rstrip任何新行或使用什么的Martijn建议,你也可以解析使用python与输出需要AWK的grep这将不添加任何新行:

您可以分割:

out = subprocess.check_output(["ifconfig", "en0"]) 

for line in out.splitlines(): 
    if line.lstrip().startswith("inet "): 
     print(line.split()[1].split(":", 2)[1]) 
     print(ip.search(line)) 
     break 

或使用您自己的正则表达式:

import re 

out = subprocess.check_output(["ifconfig", "en0"]) 

print(re.search('([0-9]{1,3}[\.]){3}[0-9]{1,3}', out).group()) 

问题的关键是你不需要的awk或者grep的。

如果要匹配IPv4或IPv6,也赶上时,有即没有这样的接口返回了一个错误,你可以搭乘CalledProcessError这将提高任何非零退出状态,很容易使用IPv4的正则表达式,但对于ipv6,使用inet6可以更简单地获取ipv6地址。

from subprocess import check_output, CalledProcessError 
import re 

def get_ip(iface, ipv="ipv4"): 
    try: 
     out = check_output(["ifconfig", iface]) 
    except CalledProcessError as e: 
     print(e.message) 
     return False 
    try: 
     if ipv == "ipv4": 
      return re.search('([0-9]{1,3}[\.]){3}[0-9]{1,3}', out).group() 
     return re.search("(?<=inet6 addr:)(.*?)(?=/)", out).group().lstrip() 
    except AttributeError as e: 
     print("No {} address for interface {}".format(ipv, iface)) 
     return False 

演示:

In [2]: get_ip("wlan0") 
Out[2]: '192.168.43.168' 

In [3]: get_ip("wlan0","ipv6") 
Out[3]: 'fe80::120b:a9ff:fe03:bb10' 

In [4]: get_ip("wlan1","ipv6") 
wlan1: error fetching interface information: Device not found 
Out[4]: False 
+0

'str.lstrip('addr:')'?这将从头开始删除字符'a','d','r'和':'。以任何顺序。如果我有IPv6地址,该怎么办? –

+0

@MartijnPieters。那么,你会寻找inet6,你也可以在':'上分割一次,有很多选项。 –

+3

关键是你不应该使用'lstrip'去除前缀。 –