没有\n的python子进程输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36422572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 17:51:50  来源:igfitidea点击:

python subprocess output without \n

python

提问by Jupiter

Here is a simple script running subprocess that retrieves IP from the ifconfigcommand output from the terminal. I have noticed that subprocess.check_output()always returns a value with \n.

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

I desire to get a return value without \n. How can this be done?

我希望在没有\n. 如何才能做到这一点?

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

回答by Benjamin

For a generic way :

对于通用方式:

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

回答by Martijn Pieters

subprocess.check_output()does notadd a newline. echodoes. You can use the -nswitch to suppress the newline, but you have to avoidusing the shell built-in implementation (so use /bin/echo):

subprocess.check_output()没有添加一个换行符。echo做。您可以使用-nswitch 来取消换行,但您必须避免使用 shell 内置实现(因此请使用/bin/echo):

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

If you use echo -ninstead, you could get the string '-n hello world\n', as not all shimplementations support the -nswitch support echo(OS X for example).

如果echo -n改为使用,则可以获得 string '-n hello world\n',因为并非所有sh实现都支持-nswitch 支持echo(例如 OS X)。

You could always use str.rstrip()or str.strip()to remove whitespace, of course, but don't blame subprocesshere:

当然,您始终可以使用str.rstrip()str.strip()删除空格,但不要subprocess在这里责怪:

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

Your question update added a more complex example using awkand grep:

您的问题更新使用awk和添加了一个更复杂的示例grep

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

Here grepadds the (final) newline. grep -omay print justthe matching text, but still adds a newline to separate matches. See the grepmanual:

这里grep添加了(最终)换行符。grep -o可能打印匹配的文本,但仍会添加一个换行符来分隔匹配项。请参阅grep手册

-o
--only-matching

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

-o
--only-matching

只打印匹配行的匹配(非空)部分,每个这样的部分在一个单独的输出行上。

Emphasis mine.

强调我的。

You can add a tr -d '\n'at the end to remove any newlines from the output of your pipe:

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

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

回答by Padraic Cunningham

You can str.rstripany newline or use what Martijn suggests, you can also parse the output using python with the need to awkor grepwhich won't add any newlines:

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

You can split:

您可以拆分:

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

Or use your own regex:

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

import  re

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

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

The point being you don't need awk or grep.

关键是你不需要 awk 或 grep。

If you want to match ipv4 or ipv6 and also catch when there is an error returned i.e no such interface you can catch a CalledProcessErrorwhich will be raised for any non zero exit status, it is easy use the regex for ipv4 but for ipv6 it is simpler to use inet6to grab the ipv6 address.

如果您想匹配 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

Demo:

演示:

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

回答by ahmad

This is what you have :

这就是你所拥有的:

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

Try this instead :

试试这个:

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