2014-01-24 5 views
6

Ich bin derzeit versucht, die folgendes zu tun:Verdoppelte Escape-Zeichen

cmd = r'sudo sed -irn "1!N; s/<ip>127.0.0.1<\/ip>(\n.*4000.*)/<ip>0.0.0.0<\/ip>\1/" /usr/something.conf' 
subprocess.Popen(cmd) 

jedoch Popen beschwert, dass \\ 1 eine ungültige Referenz. Auf sie in pdb Inspektion ich das sehen,

'sudo sed -irn "1!N; s/<ip>127.0.0.1<\\/ip>(\\n.*4000.*)/<ip>0.0.0.0<\\/ip>\\1/" /usr/something.conf' 

Es scheint, als ob Python eine zusätzliche \ erweitert. Gibt es eine Möglichkeit, das zu verhindern, so dass ich den Befehl wie Popen ausführen kann?

Auch zur Vereinfachung habe ich es aus dem Beispiel herausgelassen, aber das wird tatsächlich in einem SSH-Aufruf verpackt, bevor es an Popen übergeben wird, also ja ... es muss mit Popen und sed getan werden.

Als Referenz hier ist die vollständige Kette von Schritten die Schnur durch ...

ausgeführt werden geht
def _formatCmd(cmdString, host=None, user=None, keyfile=None): 
    cmd = [] 
    if host: 
     cmd.append('ssh') 
     keyfile = keyfile or getKeyFile() 
     if keyfile: 
      cmd.append('-i') 
      cmd.append(keyfile) 
     cmd.append("%[email protected]%s" % (user, host)) 
     cmd.append(cmdString) 
    else: 
     cmd += cmdString.split() 

    return cmd 


def runCmd(host, user, cmd, timeout=None, cleanup=False): 
    try: 
     cmd = _formatCmd(cmd, host=host, user=user) 
    except: 
     pass 

    #create cmd and add it to list of running cmds 
    proc = Popen(cmd, stdout=PIPE, stderr=PIPE) 
    runningCmds[proc.pid] = proc 

    t = threading.Timer(timeout, proc.kill) 
    t.start() 
    stdout, stderr = proc.communicate() 
    t.cancel() 

    del runningCmds[proc.pid] 
    return (proc.returncode, stdout, stderr) 

cmd = r'sudo sed -irn "1!N; s/<ip>127.0.0.1<\/ip>(\n.*4000.*)/<ip>0.0.0.0<\/ip>\1/" /usr/something.conf' 
runCmd('1.1.1.1', 'username', cmd) 

Die genaue Fehlermeldung zurückgegeben wird:

sed: -e expression #1, char 59: invalid reference \\1 on `s' command's RHS 
+2

Beachten Sie, dass 'r '\ 1'' dasselbe ist wie' '\\ 1'' ohne das' r'. Es gibt zwei Möglichkeiten, dieselbe Zeichenfolge zu schreiben. Python fügt keine zusätzlichen Backslashes hinzu. Was Sie sehen, ist pdb druckt die Zeichenfolge im nicht-raw-Modus. –

+1

Können Sie den vollständigen Code ohne Vereinfachung sowie die * genaue * Fehlermeldung, die Sie sehen, posten? Wenn Sie Probleme haben, sind alle Ebenen wichtig. –

+0

Sie entkommen eine Zeichenfolge, die nicht aufgrund der Verwendung von roher Notation ('cmd = r'string'') – mhlester

Antwort

1

Das Problem, dass die Schale macht seine eigene Interpretation/Flucht. Ähnliches habe ich bei Cygwin gefunden (im Cygwin-Fall war die Shell Bash).

Die Tatsache, dass Sie den Fehler:

sed: -e expression #1, char 59: invalid reference \\1 on `s' command's RHS 

impliziert, dass es die Klammern ist (), dass das Problem eher als das Entkommen des \1 sind. Im Wesentlichen ist es nicht in der Lage, die Gruppe zu finden, also müssen Sie die Klammern \(...\) zu entkommen.

die Ursache zu finden, ist der Trick echo zu verwenden, zu debuggen, was gesendet wird:

  1. die Regex Vereinfachen nur eine Gruppe zu und das Spiel. Etwas wie:

    s/(one)/\1\1/ 
    

    wo die Eingabezeichenfolge ist ‚Eins‘ und die erwartete Ausgabe ist oneone

  2. ändern cmd-echo so dass das, was Sie an die Shell übergeben ist echo s/(one)/\1\1/

  3. I Ich vermute, Sie werden etwas wie bash: syntax error near unexpected token '(' sehen. Das gibt uns unseren Hinweis. Grundsätzlich müssen wir den Klammern entkommen.

  4. So versuchen Sie jetzt echo s/\(one\)/\1\1. In meinem Fall sehe ich so etwas wie

    s/(one)/\1\1 
    
  5. Mit etwas Glück, die es tun sollten, und Sie sollten in der Lage, es zu problematischen Ausdruck anzuwenden.

Es kann sein, einfachste strong quoting (surrounding Befehl in einfachen Anführungszeichen) zu verwenden, die bash erzählt die Zeichenfolge nicht zu interpretieren, obwohl Sie wahrscheinlich müssen noch die Klammern () entkommen.

Als beiseite, für Cygwin Dinge müssen zweimal entkommen sein, so dass die tatsächliche richtige Ausdruck ist:

sed s/\\\(one\\\)/\\1\\1/ 

so

echo one | sed s/\\\(one\\\)/\\1\\1/ 

gibt

oneone 

Das Äquivalent mit stark zitiert ist:

echo one | sed 's/\(one\)/\1\1/' 
+0

Das Entkommen der() war alles was fehlte! Vielen Dank! – EEP

+0

@EEP - ausgezeichnet. – acarlon

Verwandte Themen