2016-04-05 111 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'去除前綴。 –