2016-04-05 8 views
6

Hier ist ein einfaches Skript, das Subprozess ausführt, der IP von der ifconfig Befehlsausgabe vom Terminal abruft. Ich habe festgestellt, dass subprocess.check_output() immer einen Wert mit \n zurückgibt.Python-Subprozess-Ausgabe ohne n

Ich möchte einen Rückgabewert ohne \n erhalten. Wie kann das gemacht werden?

$ 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' fügt hinzu, dass Newline .. –

+0

nein, nicht nur. Wenn ich 'subprocess.check_output (" ifconfig en0 | awk '{drucken $ 2}' | grep -E -o '([0-9] {1,3} [\.]) {3} [0-9] ausführen {1,3} '", shell = True)' was meine IP-Adresse auf bash Mac OS X abruft, die Return-Zeile ist auch vorhanden – Jupiter

+0

echo -n habe kein echo newline. Oder fügen Sie .strip() am Ende der Unterprozesslinie hinzu – Benjamin

Antwort

15

Für eine generische Art und Weise:

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

Dies beantwortet nicht * warum * es gibt eine neue Zeile in der Ausgabe; entweder für die Ausgabe 'echo' oder 'grep'. Hinweis: Es ist nicht 'check_output()', die es hinzufügt. –

+4

Die Frage war nicht warum, aber wie man es entfernt :-D Ich denke die Antwort ist, dass Befehlszeilen-Binärdateien eine neue Zeile am Ende ihrer Ausgaben hinzufügen, um eine nette Shell-Eingabeaufforderung zu haben (in einer anderen Zeile). – Benjamin

+0

Ich denke, wir unterscheiden uns nur in der Interpretation der Frage. * Ich habe festgestellt, dass 'subprocess.check_output()' immer einen Wert mit '\ n' * zurückgibt. Und die OP änderte die Frage, um zu zeigen, dass sie selbst mit "grep -o" immer noch diese neue Zeile erhalten (als ob sie die Antworten, die auf Echo verweisen, als die Quelle der neuen Zeile falsch darstellen). –

1

subprocess.check_output() tut nicht eine neue Zeile hinzufügen. echo tut. Sie können die -n benutzen, um das Neue-Zeile zu unterdrücken, aber Sie müssen vermeiden die Schale mit Einbau-Implementierung (so /bin/echo verwenden):

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

Wenn Sie echo -n stattdessen verwenden, könnten Sie die Zeichenfolge erhalten '-n hello world\n' , wie nicht alle sh Implementierungen unterstützen die -n Switch-Unterstützung echo (OS X zum Beispiel).

Sie könnten immer str.rstrip() oder str.strip() verwenden Leerzeichen zu entfernen, natürlich, aber nicht die Schuld subprocess hier:

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

Ihre Frage Update hinzugefügt ein komplexeres Beispiel mit awk und grep:

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

Hier grep fügt die (endgültige) Newline hinzu. grep -o kann nur den passenden Text drucken, fügt aber immer noch eine neue Zeile zu separaten Übereinstimmungen hinzu. Siehe die grep manual:

-o
--only Anpassungs

Drucken nur die angepassten (nicht leeren) Teile der Anpassungsleitungen, mit jedem solchen Teil auf einer getrennten Ausgangsleitung.

Schwerpunkt meiner.

Sie können eine tr -d '\n' am Ende fügen Sie alle Zeilenumbrüche aus dem Ausgang des Rohres zu entfernen:

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

Ich glaube nicht, dass dies eine Frage über das Echo ist, "rstrip" ist, was das OP benötigt –

+1

@PadraicCunningham: das * hängt *. Und es ist wichtig, darauf hinzuweisen, dass die Annahme, dass "check_process" diese neue Zeile hinzufügt, falsch ist. –

+1

@PadraicCunningham: Angesichts der Änderung der Frage behauptet das OP fast sicher immer noch, dass der Zeilenumbruch durch "check_output" hinzugefügt wurde. Dass Sie Zeilenumbrüche mit 'str.rstrip()' entfernen können, spielt hier keine Rolle. –

0

Sie alle Newline str.rstrip können oder verwenden, was Martijn schon sagt, können Sie auch die Ausgabe mit Python analysieren mit die Notwendigkeit, awk oder grep, die keine Zeilenumbrüche nicht hinzugefügt werden:

Sie aufspalten:

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 

Oder Ihre eigenen regex verwenden:

import re 

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

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

Der Punkt, den Sie awk oder grep brauchen nicht zu sein.

Wenn Sie IPv4- oder IPv6 passen wollen und fangen auch wenn es einen Fehler, dh keine solche Schnittstelle zurückgegeben wird, können Sie eine CalledProcessError fangen, die für jede Nicht-Null-Exit-Status erhoben wird, ist es leicht, die Verwendung der Regex für IPv4- aber Für ipv6 ist es einfacher, inet6 zu verwenden, um die IPv6-Adresse zu greifen.

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 
+0

'str.lstrip ('addr:')'? Dadurch werden die Zeichen "a", "d", "r" und ":" von Anfang an entfernt. In irgendeiner Reihenfolge. Was passiert, wenn ich eine IPv6-Adresse habe? –

+0

@MartijnPieters. Bin, dann würdest du nach inet6 suchen, du könntest auch mal auf ':' spalten, es gibt viele Möglichkeiten. –

+3

Der Punkt ist, dass Sie 'lstrip' nicht verwenden sollten, um ein Präfix zu entfernen. –

Verwandte Themen