Warum gibt sed nicht den Exit-Status zurück, wenn der reguläre Ausdruck nicht übereinstimmt?

8

Ich versuche, eine Zeile aus Dateien zu suchen und zu ersetzen, aber wenn ich sie ausführe, sedwenn dieser reguläre Ausdruck nicht übereinstimmt, sedwird kein Statuscode zurückgegeben. Anstatt also eine weitere Bedingung mit hinzuzufügen grep, gibt es einen Weg hinein sedund Warum sedwird der Exit-Status nicht zurückgegeben ?

Problem :

Geben Sie hier die Bildbeschreibung ein

Rahul Patil
quelle
1
Dieser wurde auf StackOverflow, stackoverflow.com/questions/15965073/…
Drav Sloan
1
@DravSloan - es ist in Ordnung, einige der Antworten hier zu replizieren.
slm

Antworten:

15

sed gibt einen Exit-Status zurück:

$ echo "foo" | sed 's/xx/yy/'
foo
$ echo $?
0
$ sed 's/xx/yy/' foo.txt
sed: can't read foo.txt: No such file or directory
$ echo $?
2

In den Exit-Codes von Sed geht es darum, ob das Programm erfolgreich beendet wurde oder nicht. Sie haben nichts mit den Interna zu sedtun, sondern nur damit, ob der Befehl ausgeführt werden konnte oder nicht.

Trotzdem bietet GNU sed eine Möglichkeit, dies zu tun:

   q [exit-code]
          Immediately  quit  the sed script without pro‐
          cessing any more input, except that  if  auto-
          print  is  not  disabled  the  current pattern
          space will be printed.  The exit code argument
          is a GNU extension.

Zum Beispiel (von hier genommen ):

$  echo "foo"|sed '/foo/ s/f/b/;q'                                                                       
boo
$  echo $?
0
$ echo "trash"|sed  '/foo/{s/f/b/;q}; /foo/!{q100}'
trash
$  echo $?
100

Wenn Sie die Tatsache melden möchten, dass eine Substitution in einer Zeile der Eingabe erfolgreich war, können Sie erfolgreiche Substitutionen im Haltebereich markieren und in der letzten Zeile überprüfen:

seq 6 | sed 's/4/four/;s/5/five/; tm;${x;/1/{x;q};x;q1};b;:m;x;s/.*/1/;x'

tmVerzweigt zum mEtikett, wenn eine Substitution erfolgreich war. Dort setzen wir 1den Laderaum ein, den wir in der letzten Zeile suchen.

terdon
quelle
Der Exit-Code von egrep gibt jedoch Auskunft über den Befehl, der ausgeführt wird. Es muss also nicht sein, dass dies nicht der Fall ist.
JohnyTex
@ JohnyTex niemand sagte, dass es musste. Dies grepist jedoch keine gute Analogie. Grep ist ein einfaches Programm, das nur eines kann: nach Mustern suchen. Wenn es es nicht findet, kann es Sie wissen lassen. Es sedist jedoch etwas völlig anderes und weitaus komplexer. Es ist im Grunde eine Skriptsprache, mit der Sie beliebige Aufgaben ausführen können. Es kann nicht festgestellt werden, ob es "erfolgreich" war, da der Erfolg von den Details des Skripts abhängt, das Sie ausführen. Wie in allen Programmiersprachen ist es daher Sache des Programmierers, den Exit-Status zu definieren.
Terdon
"Exit-Codes handeln davon, ob ein Programm erfolgreich beendet wurde oder nicht ..." scheint zu implizieren, dass sie keine andere Funktion haben können ... Vielleicht nur ein wenig klären.
JohnyTex
@JohnyTex Ich beziehe mich auf die Exit-Codes von sed, nicht auf die Exit-Codes im Allgemeinen. Was der Exit-Code eines Programms bewirkt, hängt vollständig von dem Programmierer ab, der ihn geschrieben hat.
Terdon
Ich verstehe das. Ich denke nur, dass die Formulierung ein bisschen unglücklich ist, obwohl es mich eigentlich nicht so sehr interessiert.
JohnyTex
6

Zunächst geben alle Befehle, einschließlich sed, einen Exit-Status zurück. Sie suchen nach dem Grund, warum ich einen Fehler nicht zurückgeben würde. Was zum zweiten Punkt führt.

Programme wie sedsind Editoren, keine Prädikate. Sie dienen dazu, die durch das Programm fließenden Daten zu ändern. Fehlerbedingungen gelten für Bedingungen wie ungültige interne Befehle oder eine nicht vorhandene Datei in der Befehlszeile.

Ich bin mir nicht sicher, welche Logik Sie wollen - Sie schließen keine erwartete Ausgabe ein -, aber dies könnte das sein, wonach Sie suchen:

$ sed '/^test line 7/s//#test line 7/;/^#test line 7/s//& \nAppend New Line/' test.txt
test line 1
test line 2
test line 3
test line 4
test line 5
test line 6
#test line 7
Append New Line

Es gibt andere Konstrukte, die dies ebenfalls verarbeiten können, beispielsweise den bBefehl (branch) in sed.

Wenn Sie einen tatsächlichen Rückkehrcode wünschen, falls dieser nicht gefunden wird, sollten Sie sich gawkdessen exitAnweisung ansehen .

Arcege
quelle
Trotzdem wird immer wieder eine Zeile angehängt, wenn wir immer wieder rennen.
Rahul Patil
Ich habe mit grep gelöst, möchte es aber in sed wissen .. github.com/rahulinux/bash-functions-/blob/master/…
Rahul Patil
Sie möchten die zweite Anweisung nur ausführen, wenn die erste erfolgreich ist? Sie können den GNU-Erweiterungsbefehl Tzwischen den beiden hinzufügen :sed -i '/^test line 7/s//#&/;T;/#test line 7/&\nAppend New Line/' test.txt
Arcege