2016-03-25 5 views
2

Informationen über die Umwelt Ich arbeite in:Was ist der Unterschied s/w zwei sed Befehle unten?

$ uname -a 
AIX prd231 1 6 00C6B1F74C00 
$ oslevel -s 
6100-03-10-1119 

-Code Block A

(grep schdCycCleanup $DCCS_LOG_FILE | sed 's/[~]/ \ 
/g' | grep 'Move(s) Exist for cycle' | sed 's/[^0-9]*//g') > cycleA.txt 

Codeblock B

(grep schdCycCleanup $DCCS_LOG_FILE | sed 's/[~]/ \n/g' | grep 'Move(s) Exist for cycle' | sed 's/[^0-9]*//g') > cycleB.txt 

Ich habe zwei Codeblöcke (siehe oben), die sed verwenden, um den Eingang auf 6 Stellen zu reduzieren, aber ein Befehl verhält sich anders als erwartet.

Probe von Input für die zwei Codeblöcke

Mar 25 14:06:16 prd231 ajbtux[33423660]: 20160325140616:~schd_cem_svr:1:0:SCHD-MSG-MOVEEXISTCYCLE:200705008:AUDIT:~schdCycCleanup - /apps/dccs/ajbtux/source/SCHD/schd_cycle_cleanup.c - line 341~ SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210~ 

ich die folgende Ausgabe, wenn die Probe über Eingabe durch die beiden Codeblöcke geht.

cycleA.txt Inhalt

389210 

cycleB.txt Inhalt

25140616231334236602016032514061610200705008341389210 

Ich verstehe, dass meine letzte sed-Befehl (sed ‚s/[^ 0-9] verrohrt * // g ') löscht alle Zeichen außer Ziffern, also habe ich sie aus den Blockcodes weggelassen und die Ausgabe in zwei zusätzliche Dateien eingefügt. Ich bekomme folgende Ausgabe.

cycleA1.txt Inhalt

SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210 

cycleB1.txt Inhalt

Mar 25 15:27:58 prd231 ajbtux[33423660]: 20160325152758: nschd_cem_svr:1:0:SCHD-MSG-MOVEEXISTCYCLE:200705008:AUDIT: nschdCycCleanup - /apps/dccs/ajbtux/source/SCHD/schd_cycle_cleanup.c - line 341 n SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210 n 

kann ich sehen, dass der erste Codeblock alles andere, dass (SCHD_CYCLE_CLEANUP abzieht - Move (s) existiert für Zyklus 389210) und verwendet die Tilde, aber der zweite Codeblock ersetzt gerade ti Ides mit dem Zeichen n. Ich kann auch sehen, dass es in dem ersten Codeblock für einen Zeilenumbruch nach diesem (sed 's/[~] /) notwendig ist, und deshalb würde ich \ n einen Zeilenumbruch simulieren, aber das ist nicht der Fall. Ich denke meine verschiedenen Ausgabeergebnisse sind wegen der Art, wie reguläre Ausdrücke benutzt werden. Ich habe versucht, in reguläre Ausdrücke zu suchen und habe sie auf Stackoverflow untersucht, aber nicht bekommen, wonach ich gesucht habe. Könnte jemand erklären, wie ich das gleiche Ergebnis von Codeblock B wie Codeblock A erreichen kann, ohne dass ein Teil meines Codes in einer zweiten Zeile steht?

Vielen Dank im Voraus

+0

Welche Version von 'sed' verwenden Sie? Ich habe Version 4.2.1 und ich bekomme die gleichen Ergebnisse mit beiden "sed" -Ausdrücken. – lurker

+0

Sie können die Beispieleingabe und -ausgabe mithilfe der Codeformatierung anstelle der Anführungszeichenformatierung neu formatieren, um sicherzustellen, dass Zeilenumbrüche/etc. werden korrekt angezeigt? –

+0

Es ist eine gute Frage, aber es ist in Lärm begraben. Ziehen Sie in Betracht, ein [MCVE (minimales, vollständiges und verifizierbares Beispiel)] (http://stackoverflow.com/help/mcve) zu erstellen. – mklement0

Antwort

2

Etan Reisner's helpful answer erklärt das Problem und bietet eine einzeilige Lösung auf der Basis eines ANSI C-quoted string ($'...'), die geeignet ist, da Sie ursprünglich Ihre Frage getaggt.
(Ed Morton's helpful answer zeigt Ihnen, wie Sie Bypass Ihr Problem zusammen mit einem anderen Ansatz, die sowohl einfacher und effizienter ist.)

aber es klingt wie Shell eigentlich etwas anderes ist - vermutlich ksh88, eine ältere Version des Korn-Shell, die den Standard sind sh auf AIX 6.1 - in denen solche Strings sind nicht unterstützt [1] (ANSI C-Strings in Anführungszeichen wurden in ksh93 eingeführt, und auch Unterstützung Ed nicht nur in bash, sondern auch in zsh).

So haben Sie folgende Optionen :

  • Mit Ihrem aktuell Shell, müssen Sie bleiben mit einer zweizeiligen Lösung, die einen (\ -escaped) enthält tatsächliche Newline, wie in Ihrem Codeblock A.

    • Beachten Sie, dass $(printf '\n') zum Erstellen einer Newline tut nicht Arbeit, weil Befehlsersetzungen ausnahmslos alle nachfolgenden Zeilenumbrüche trimmen, was in diesem Fall die leere Zeichenfolge in diesem Fall.
  • eine modernere Shell verwenden, die ANSI-C-Strings in Anführungszeichen unterstützt, und Etan Antwort verwenden. http://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.cmds3/ksh.htm sagt mir, dass ksh93ist als alternative Shell auf AIX 6.1, wie /usr/bin/ksh93.

  • Wenn möglich: installieren GNUsed, die Escape-Sequenzen wie \n in Ersatzzeichenfolgen nativ versteht.


[1] Als für das, was tatsächlich passiert, wenn man echo 'foo~bar~baz' | sed $'s/[~]/\\\n/g' in einem POSIX-artig Shell versuchen, das tut nicht Unterstützung $'...': die $ gelassen wird, wie sie ist, weil das, was folgt ist ein gültiger Variablenname, und sed landet sehen, Literal $s/[~]/\\\n/g, wo die $ als eine Kontextadresse für die letzten Eingangszeile interpretiert wird - was hier keinen Unterschied macht, denn es gibt nur Linie. \\ wird als einfach \ interpretiert und \n als einfach n, effektiv ersetzt ~ Instanzen mit Literal\n Sequenzen.

+0

Vielen Dank für die Antwort. Ich habe zufällig ksh93, wie Sie im Verzeichnis/usr/bin/ksh93 angegeben haben. Wenn ich Etans Antwort im Skript testen wollte, würde es ausreichen, die erste Zeile in meinem Skript von #!/Bin/ksh in #!/Bin/ksh93 zu ändern? – ManaFive

+0

@ManaFive: Verwende '#!/Usr/bin/ksh93' um sicher zu sein, dh den _vollen Pfad_ zur Binärdatei (es gibt Plattformen, zB Fedora, wobei'/bin' ein Symlink zu '/ usr/bin' ist , aber das ist im Allgemeinen nicht der Fall). Eine Alternative ist die Verwendung von '#!/Usr/bin/env ksh93', wodurch das Standardwerkzeug' env' das Binärprogramm im '$ PATH' findet (obwohl es sich in diesem Fall im selben Verzeichnis befindet wie' ' env' selbst.) – mklement0

2

GNU sed Griffe \n im Austausch so, wie Sie erwarten.

OS X (und vermutlich BSD) sed nicht. Es behandelt es als normales Escape-Zeichen und lässt es einfach zu n unescapes.(Obwohl ich das momentan nirgendwo im Handbuch sehe.)

Sie können $'' verwenden, um \n als wörtlichen Zeilenumbruch zu verwenden, wenn Sie möchten.

echo 'foo~bar~baz' | sed $'s/[~]/\\\n/g' 
+2

++; BSD/OS X 'sed' bleibt in der Nähe der POSIX-Spezifikation. (Die einzigen genannten Erweiterungen sind '-E',' -a' und '-i') und die [POSIX-Spezifikation] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html) deklariert die Interpretation von '\ n' in der Ersetzungszeichenfolge _unspecified_ (weil' n' ein Zeichen ist, das nicht entfernt werden muss). In der Praxis kann ich bestätigen, dass neuere Versionen von FreeBSD/PC-BSD/OS X '\ n' als einfaches' n' interpretieren. – mklement0

+0

Hallo Etan, ich lief dein Beispiel auf der Unix-Box und hatte die folgende Ausgabe 'echo' foo ~ bar ~ baz '| sed $ 's/[~]/\\\ n/g' foo \ nbar \ nbaz' Die Tilden wurden ersetzt durch \ n – ManaFive

+0

@ProudAtheist Das '$ '..' 'Ding ist ein Bash-ism, glaube ich. Sie laufen ksh, nicht bash, also ... Interessante Wahl des Benutzernamens übrigens - nichts, als ob Sie Ihre Religion an jedermann schreien würden, um für eine angenehme Umgebung zu sorgen. –

5

Dies ist ein Beispiel für das XY-Problem (http://xyproblem.info/). Sie bitten um Hilfe, um etwas zu implementieren, das die falsche Lösung für Ihr Problem ist. Warum ändern Sie ~ s Zeilenumbrüche, etc, wenn alle geposteten Abtastwerteingang und erwartete Ausgabe gegeben müssen, ist:

$ sed -n 's/.*schdCycCleanup.* \([0-9]*\).*/\1/p' file 
389210 

oder:

$ awk -F'[ ~]' '/schdCycCleanup/{print $(NF-1)}' file 
389210 

Wenn das nicht alles müssen Sie dann bitte bearbeiten: Frage zu klären, Ihre Anforderungen für WAS Sie versuchen zu tun (im Gegensatz zu WIE du versuchst es zu tun) als Ihre aktuelle Vorgehensweise ist einfach falsch.

+0

Hallo Ed, ich wollte wirklich wissen, warum Codeblock B nicht die gleichen Ergebnisse wie Codeblock A erzeugt hat. Sie alle konnten mich mit der Tatsache aufklären, dass '\ n' nicht verwendet werden kann eine neue Zeile in meiner aktuellen Shell. Ich bin Ihnen allen dankbar, die ihre Zeit investiert haben und dadurch ein besseres Verständnis gewonnen haben. – ManaFive

+1

@ManaFive die Antwort auf diese Frage hatte nichts mit Ihrer Shell zu tun, es ist, dass '\ n 'ist nicht übertragbar über sed-Versionen und die Version von sed Sie laufen nicht unterstützt es. –

Verwandte Themen