没有python子进程输出

2024-05-23 18:50:27 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是一个运行子进程的简单脚本,它从终端输出的ifconfig命令中检索IP。 我注意到subprocess.check_output()总是返回一个带有\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'

Tags: import命令ip脚本终端output进程check
3条回答

一般来说:

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

subprocess.check_output()不添加新行。echo是的。可以使用-n开关来抑制换行符,但必须避免使用shell内置实现(因此使用/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)。

当然,您可以始终使用^{}^{}来删除空白,但不要责怪这里的subprocess

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

您的问题更新使用awkgrep添加了一个更复杂的示例:

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

此处grep添加(最终)换行符。grep -o可能只打印匹配文本,但仍会添加新行来分隔匹配。请参阅^{} manual

-o
--only-matching

Print only the matched (non-empty) parts of matching lines, with each such part on a separate output line.

强调我的。

您可以在末尾添加^{}以从管道输出中删除任何新行:

>>> 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'

您可以str.rstrip任何换行符或使用Martijn建议的内容,还可以使用python解析输出,需要awkgrep而不添加任何换行符:

您可以拆分:

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

或者使用自己的regex:

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的regex,但对于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

相关问题 更多 >