Diesen einfachen regulären Ausdruck in grep abgleichen

2543
barlop

Ich möchte ein Zitat, 2ein Leerzeichen und jedes Zeichen, das kein Punkt ist, zusammenbringen.

Dies verwendet GnuWin32 grep. Nicht Cygwins Grep.

C:\>echo "2 008abc.html" | grep -oiP \"2 [^.] grep: [^.]': No such file or directory  C:\>echo "2 008abc.html" | grep -oiP ^"2 [^.]  C:\>echo "2 008abc.html" | grep -oiP """2 [^.] grep: [^.]: No such file or directory  C:\>echo "2 008abc.html" | grep -oiP """2 0 grep: 0: No such file or directory  C:\>echo "2 008abc.html" | grep -oiP """"2 0" "2 0   C:\>echo "2 008abc.html" | grep -oiP """"2 [^.]"  C:\>echo "2 008abc.html" | grep -oiP """"2 0" "2 0 

(Ich habe meine eigene Frage in der vorherigen Überarbeitung beantwortet, es ist nicht nötig, darauf zu verweisen, aber dies führt zu einem weiteren stark verwandten Übereinstimmungsproblem. Ich habe diese Frage also überarbeitet, um etwas sehr Ähnliches zu finden, das jedoch auf ein Problem stößt.)

-2

2 Antworten auf die Frage

2
juggler

Es sieht so aus, als würden Sie Windows Command Prompt ( cmd.exe) als Shell verwenden, und Sie werden durch die Zitierkonventionen gestolpert oder nicht. Wenn ich Ihren Befehl in einer Fedora 15- Bash-Shell ausführen, funktioniert er. Wenn ich es unter Windows mit der Cygwin-Bash-Shell starte, funktioniert es.

Damit es funktioniert cmd.exe, müssen Sie die Anführungszeichen und den Abstand ändern. Ich habe die folgenden Befehle in cmd.exeWindows 7 ausgeführt. Beachten Sie, wie ich die Anführungszeichen im Befehl grep so geändert habe, dass Anführungszeichen anstelle von Anführungszeichen verwendet werden. Vor der Pipe ( |) steht kein Leerzeichen .

Ich verwende die Cygwin-Version von GNU-grep, die sich wie Ihre Win32-GNU-grep verhalten sollte.

c:\>c:\cygwin\bin\grep --v GNU grep 2.6.3  Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.  c:\>echo "2008abc.html"| c:\cygwin\bin\grep -oiP '\"[^.]' "2 

Wenn vor der Pipe ein Leerzeichen vorhanden ist, wird das Leerzeichen durch die Pipeline wiederholt, und grep stimmt mit diesem überein. Dies liegt an dem idiotischen Parsenverhalten von cmd.exe.

c:\>echo "2008abc.html" | c:\cygwin\bin\grep -oiP '\"[^.]' "2 " 

Überprüfen Sie zu Ihrer eigenen Vernunft, ob Sie Cygwins Bash oder eine andere Shell mit angemessenen und konsistenten Zitierkonventionen verwenden können.

Wie sind die Windows-Zitierkonventionen nicht sinnvoll oder konsistent? barlop vor 12 Jahren 0
und was ist das Problem mit einfachen Anführungszeichen und doppelten Anführungszeichen? Übrigens, Ihre Zeile hat funktioniert "\" [^.] " barlop vor 12 Jahren 0
Ich weiß nicht, warum es mit einfachen Anführungszeichen und nicht mit doppelten Anführungszeichen funktioniert, aber es funktioniert in jeder Hinsicht gut, wenn Sie die bash-Shell anstelle von cmd.exe verwenden. Ich habe genug seltsame Probleme mit Anführungszeichen und Abständen in cmd.exe gesehen, die ich vermeide und wann immer möglich Cygwin-Bash verwende. juggler vor 12 Jahren 0
@ barlop: Die Unterschiede sind, dass das Programm in Windows seine Befehlszeile selbst parsen muss (in Unix wird dies von der Shell: sh oder bash erledigt; in Cygwin von der cygwin1.dll-Laufzeit), und Windows verwendet \ als Pfadtrennzeichen (bash behandelt es als Escape-Zeichen). Viele Probleme treten auf, wenn Sie Cygwin-Programme mit Pfadnamen im Windows-Stil verwenden. (Wie sollte beispielsweise das letzte \ in "C: \ WINDOWS \" analysiert werden? Sollte dies in Cygwin und einem nativen Windows-Programm anders funktionieren?) grawity vor 12 Jahren 0
@grawity Probleme bei der Verwendung von \ dir \ prog für cygwin und / dir / prog für Windows sind reine Dummheit des Benutzers und keine Dinge, die ein Technikfreak tun würde, ich frage nicht nach dieser Art von Problem. Was den letzten Schrägstrich angeht, sehe ich nicht, wie es ein Problem ist, aber das Problem damit, * nix hat nicht auch die Frage des letzten Schrägstrichs oder nicht. Ich bemerke in Cygwin, dass "echo * /" nach jedem Verzeichnisnamen einen Schrägstrich setzt. Während "echo *" nach keinem Verzeichnisnamen einen Schrägstrich setzt. Und * nix interpretiert cd z / sowie cd z barlop vor 12 Jahren 0
Das war * total * nicht mein Punkt. grawity vor 12 Jahren 0
@grawity Nun, was meinen Sie mit " Cygwin-Programmen mit Pfadnamen im Windows-Stil"? ? barlop vor 12 Jahren 0
@barlop: `grep -r foo" C: \ Dokumente und Einstellungen \ Simon Travaglia \ "` aus der Windows-Shell cmd.exe. Fungiert der letzte Backslash als Pfadtrennzeichen? Oder entgeht es dem ""? Ähnliches für "\ D", "\ S". Ein anderes Beispiel: "somecommand" funky \ "characters" `- ist das eine Argument *" funky "Zeichen" * oder zwei Argumente * `funky \` * und * `Zeichen` *? grawity vor 12 Jahren 0
@ barlop: Noch ein weiteres: `cmd / c somecommand" foo bar "`, in dem alles nach `/ c 'als einziges Argument gelesen wird, obwohl es nicht in Anführungszeichen steht. Hier kommt die Inkonsistenz ins Spiel. Im Vergleich dazu hat bash strenge Regeln, nach denen jede Eingabezeile auf dieselbe Weise analysiert wird. grawity vor 12 Jahren 0
@ gordoco Entschuldigung gordoco, ich habe Ihre Antwort abgewählt. Ich habe gerade festgestellt, dass Sie für cygwins grep geantwortet haben, und Sie haben das seltsame getan, sie von CMD.EXE aufzurufen. Normalerweise werden cygwin-Befehle innerhalb von cygwin ausgeführt, wie etwa cygwin.bat zuerst. Zufällig stelle ich fest, dass "2008abc.html" | grep -oiP \ "[^.] <- funktioniert, Sie waren falsch. Ich denke, in den einfachen Anführungszeichen haben sie das Gleiche getan, was für gnuwin32 nicht der Fall ist, also hat Ihre Antwort nicht für gnuwin32's getan Ich habe nach gefragt. barlop vor 12 Jahren 0
Ich verstehe, was Sie damit meinen, cmd / c dir ab, nimmt es als cmd / c "dir ab" und versagt nicht wie Runas, wenn der Programmparameter Leerzeichen enthielt und nicht in Anführungszeichen gesetzt wurde, sondern ein beliebiges Programm in einem cmd Eingabeaufforderung, könnte alle Parameter zu einem kombinieren. kann kein Linux-Programm das auch? oder kombinieren oder trennen, wie es will, und deshalb auch "inkonsistent" sein? barlop vor 12 Jahren 0
@barlop: Nicht immer. In Unix-Shells können Sie "foobar", "foobar", "foobar", "fo" ob'ar "" verwenden, aber die * shell * behandelt das Word-Splitting und das, was an execv übergeben wird ( ) und was das Programm in argv [] empfängt, ist immer dieselbe 6-Byte-Zeichenfolge * `foobar` *. Wenn Sie `" foo bar "` eingeben, haben Sie argv [1] als * `foo bar` *. Wenn Sie `" foo "" bar "" eingeben, haben Sie argv [1] als * `foo` * und argv [2] als *` bar` *. Zum Vergleich erhalten Win32-Programme immer einen * einzigen * String von GetCommandLine (), und das gesamte Dequoting wird vom Programm selbst ausgeführt - wenn überhaupt. grawity vor 12 Jahren 0
@ barlop: Fortsetzung meines Beispiels für den Dateinamen. Wenn Sie in Unix-Shells eine doppelte Anführungszeichenfolge haben und einen Backslash verwenden, wird der Backslash immer gleich behandelt: ein Escape für das folgende Zeichen. Die Shell wendet auf alle Befehle die gleichen Regeln an. Unter Windows können Programme, da sie es selbst tun, an einigen Stellen als Fluchtweg und an anderen als Pfadtrennzeichen behandelt werden. Betrachten Sie erneut die folgende Befehlszeile: `somecmnd" foo bar \ "baz" qux ". Angenommen, Sie befinden sich auf einem System, das \ als Pfadtrennzeichen verwendet. Wie würden Sie die Befehlszeile in separate Argumente aufteilen? grawity vor 12 Jahren 0
@grawity Ich habe http://pastebin.com/28Q2Wxxr mit TCC win32 kompiliert. Und in cygwin mit gcc kompiliert laufen. Die Werte in argsv scheinen zwischen Windows und * nix gleich zu sein. und es dequotes es .. Wie ich gehört habe ist es wahr, dass Win32 C-Programme im Gegensatz zu * nix-Programmen als eine einzige Zeichenfolge gegeben werden, aber man sieht das nicht, da es geteilt wird (und es scheint dequotiert zu sein). noch bevor die Hauptmethode ausgeführt wurde. Sehen Sie also immer noch nicht, wo der Raum für Inkonsistenzen relativ zu * nix-Programmen ist. barlop vor 12 Jahren 0
(wird in Kürze den weiteren Kommentar prüfen) barlop vor 12 Jahren 0
@grawwity Sie können \\ für ein wörtliches \ und \ "für ein wortwörtliches Zitat verwenden. Ich denke, Sie wissen das. Ich weiß nicht, was Sie mit einem System meinen, das \ als Pfadtrennzeichen verwendet, das einzige Systeme, mit denen ich vertraut bin, sind Fenster und bis zu einem gewissen Grad Unix, und der Windows-Fall verwendet natürlich \ in Pfaden, so dass ich möglicherweise Ihren Standpunkt verfehle. barlop vor 12 Jahren 0
Lassen Sie uns [diese Diskussion im Chat fortsetzen] (http://chat.stackexchange.com/rooms/1325/discussion-between-grawity-and-barlop). grawity vor 12 Jahren 0
0
barlop

Dies ist eine Lösung.

C:\>echo "2 008abc.html" | grep -oiP \"2" "[^.] "2 0 

Dieses Experiment hat geholfen (w is w.exe, wc wurde kompiliert)

C:\>w \"2\ [^.] argv[0] = w argv[1] = "2\ argv[2] = [^.]  C:\>w \"2" "[^.] argv[0] = w argv[1] = "2 [^.]  C:\> 

Hier ist eine andere Lösung

C:\>echo "2 008abc.html" | grep -oiP "\"2 [^^.]" "2 0 

Was Sie, wie Sie sehen können, fand ich nach ein wenig Fummeln, obwohl ziemlich schnell gefunden

W:\other>w "\"2 [^.]" argv[0] = w argv[1] = "2 [.]  W:\other>w "\"2 [\^.]" argv[0] = w argv[1] = "2 [\.]  W:\other>w "\"2 [^.]" argv[0] = w argv[1] = "2 [.]  W:\other>w "\"2 [^^.]" argv[0] = w argv[1] = "2 [^.] 

Toilette

#include <stdio.h>  int main(int argc, char *argv[]) { int i = 0; while (argv[i]) { printf("argv[%d] = %s\n", i, argv[i]); i++; } return 0; } 

dieses ist vor wc nützlich. Sie können es verwenden, um genau zu sehen, was von bash entfernt wird. xc

#include <stdio.h> #include <windows.h>  int main(int argc, char *argv[]) { printf(GetCommandLine()); return 0; } 

Ex-

C:\>x & x C:\> C:\>x ^& x & C:\>