staging.inyokaproject.org

Sed Replace mit Exit Code

Status: Ungelöst | Ubuntu-Version: Kubuntu 19.10 (Eoan Ermine)
Antworten |

uhuntu

Avatar von uhuntu

Anmeldungsdatum:
19. Februar 2007

Beiträge: 338

Hallo,

ich suche in einer Datei einen Ausdruck und eine Zeile nach dem gefunden Ausdruck ersetze ich einen weiteren Ausdruck. Ich möchte einen ExitCode wenn erfolgreich ersetzt wurde.

Testdatei mit folgenden Einträgen:

foo
bar
zoo

Das schaut gut aus sucht nach foo und ersetzt bar mit bar1 → Return Code 0

1
2
3
4
5
6
Code
sed  '/foo/ {n;s/bar/bar1/;t;q1}' sedtest; echo $?
foo
bar1
zoo
0

Das schaut auch gut aus bar wird nicht ersetzt da sdf nicht nach foo gefunden wird → Return Code 1

1
2
3
4
sed  '/foo/ {n;s/sdf/bar1/;t;q1}' sedtest; echo $?
foo
bar
1

Das gibt 0 aus sollte aber 1 ausgeben da bla nicht gefunden wird - wie kann ich das ändern?

1
2
3
4
5
sed  '/bla/ {n;s/bar/bar1/;t;q1}' sedtest; echo $?
foo
bar
zoo
0

Ich dachte dass ich das ev. → so

1
sed  '/foo/!{q2}; {n;s/bar/bar1/;t;q1}' sedtest; echo $?

abfangen kann, aber das gibt immer 2 aus? Wie kann ich das erste suchen auch abfangen? Das funktioniert auch so

1
2
3
4
5
6
7
8
echo "trash" | sed  '/foo/!{q100}; {s/f/b/}'; echo $?
trash
100

echo "trash" | sed  '/trash/!{q100}; {s/t/b/}'; echo $?
brash
0

thx uhuntu

Bearbeitet von rklm:

Codeblock für Dateiinhalt

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Na, ich denke, dein Problem ist, dass sed zeilenbasiert arbeitet.

Wo Du also sagst:

aber das gibt immer 2 aus

Findet es in der zweiten Zeile kein foo und bricht daher mit Exitcode 2 ab (wobei für die aktuelle Zeile noch der Code dahinter ausgeführt wird).

Was möchtest Du genau erreichen? Ich habe deine eigentliche Intention noch nicht verstanden. Du sagst:

Ich möchte einen ExitCode wenn erfolgreich ersetzt wurde.

Was meinst Du damit? Ein Programm hat immer einen Exitcode.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Dein Testszenario ist verwirrend - Du wechselst den Sedcode, um unterschiedliches Verhalten zu zeigen; normalerweise ändert man nur den Input und lässt den Programmcode fix:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
t201:~/proj/mini/forum > echo -e "xfoobar\nfoobar2foo" | sed  '/foo/ {n;s/bar2/--hit--/;t;q1}';  echo $?
xfoobar
foo--hit--foo
0
t201:~/proj/mini/forum > echo -e "xfoobar\nfoobar1foo" | sed  '/foo/ {n;s/bar2/--hit--/;t;q1}';  echo $?
xfoobar
foobar1foo
1
t201:~/proj/mini/forum > echo -e "xfoxbar\nfoobar2foo" | sed  '/foo/ {n;s/bar2/--hit--/;t;q1}';  echo $?
xfoxbar
foobar2foo
0

Ich weiß auch nicht genau, was Du anstrebst. Hier ein übersichtlicherer Code foo/fox, bar/baz. Der Teil nach der Pipe immer gleich, wie man das erwartet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
t201:~/proj/mini/forum > echo -e "foo\nbar" | sed ': go /foo/ {n; s/bar/---/;T go;q1}' ; echo $?
foo
---
1
t201:~/proj/mini/forum > echo -e "fox\nbar" | sed ': go /foo/ {n; s/bar/---/;T go;q1}' ; echo $?
fox
bar
0
t201:~/proj/mini/forum > echo -e "fox\nbaz" | sed ': go /foo/ {n; s/bar/---/;T go;q1}' ; echo $?
fox
baz
0
t201:~/proj/mini/forum > echo -e "foo\nbaz" | sed ': go /foo/ {n; s/bar/---/;T go;q1}' ; echo $?
foo
baz
0

Willst Du, wenn nirgends ein foo gefunden wurde, einen anderen Exitcode?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Was genau willst Du eigentlich erreichen? Soll die Eingabe komplett gespiegelt werden und der Exit-Code != 0 sein, falls keine einzige Ersetzung gemacht wurde? Das würde ich dann eher mit awk machen. Das ist deutlich bequemer für so etwas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ cat data-1
foo
bar
zoo
$ awk 'found {replacements+=gsub(/bar/,"bar1")} {print} /foo/ {found=1} END {if (!replacements) exit 1}' data-1; echo $?
foo
bar1
zoo
0
$ cat data-2
foo
Tar
zoo
$ awk 'found {replacements+=gsub(/bar/,"bar1")} {print} /foo/ {found=1} END {if (!replacements) exit 1}' data-2; echo $?
foo
Tar
zoo
1

uhuntu

(Themenstarter)
Avatar von uhuntu

Anmeldungsdatum:
19. Februar 2007

Beiträge: 338

Hallo, also einfacher erklärt → ich habe eine Datei:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
eins
foo
zwei
foo
drei
foo
vier
bar
fünf
foo

Ich will nach z.B. zwei suchen und eine Zeile weiter, schauen ob foo vorhanden ist und dann das foo ersetzen. foo kommt öfter vor mit der Zeile davor kann ich die Zeile aber eindeutig (zwei->foo ) identifizieren. Wenn foo nun ersetzt wird soll exitcode 0 kommen - sonst wenn z.B. zwei und eine Zeile weiter foo nicht gefunden wird dann exitcode 1.

thx

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

uhuntu schrieb:

Ich will nach z.B. zwei suchen und eine Zeile weiter, schauen ob foo vorhanden ist und dann das foo ersetzen. foo kommt öfter vor mit der Zeile davor kann ich die Zeile aber eindeutig (zwei->foo ) identifizieren. Wenn foo nun ersetzt wird soll exitcode 0 kommen - sonst wenn z.B. zwei und eine Zeile weiter foo nicht gefunden wird dann exitcode 1.

Und die Ausgabe soll komplett kommen? Ich glaube, mit sed geht das nicht - oder wird zumindest ziemlich umständlich. Das ist genau das, was mein awk-Skript machen sollte; da war noch ein Fehler, weil found nicht korrekt zurückgesetzt wurde.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cat data-1
foo
bar
zoo
bar
$ awk 'found {replacements+=gsub(/bar/,"bar1")} {print} {found=match($0,/foo/)} END {if (!replacements) exit 1}' data-1; echo $?
foo
bar1
zoo
bar
0
$ cat data-2
foo
Tar
zoo
bar
$ awk 'found {replacements+=gsub(/bar/,"bar1")} {print} {found=match($0,/foo/)} END {if (!replacements) exit 1}' data-2; echo $?
foo
Tar
zoo
bar
1

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

uhuntu schrieb:

Ich will nach z.B. zwei suchen und eine Zeile weiter, schauen ob foo vorhanden ist und dann das foo ersetzen. foo kommt öfter vor mit der Zeile davor kann ich die Zeile aber eindeutig (zwei->foo ) identifizieren. Wenn foo nun ersetzt wird soll exitcode 0 kommen - sonst wenn z.B. zwei und eine Zeile weiter foo nicht gefunden wird dann exitcode 1.

Dass zwei mehr als 1x vorkommt oder gar nicht kann eigentlich ausgeschlossen werden?

Die Zeile nach zwei besteht auch nur aus foo, nicht etwa auch mal aus xfooy?

Was, wenn schon bar1 auf zwei folgt? Auch auszuschließen bzw. auch exit!=0 zurückgeben?

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

Man kann die Umständlichkeiten bei sed umgehen, in dem man mit grep vorab ermittelt, ob es was zu ersetzen gibt:

1
2
3
4
5
6
7
ecode=7
grep -A1 zwei foobar.lst | (read zwo; read dro
test "$dro" == "foo" && ecode=0
sed '/zwei/ {n;s/foo/bar/}' foobar.lst
# exit $ecode
echo $ecode
); 

grep -A1 gibt noch eine Zeile after der Fundstelle aus. Die runden Klammern erlauben es zwei Zeilen aus der Pipeline zu lesen, die jedoch in einer Subshell laufen - daher ist ecode außerhalb weiterhin 7 und der Rest der Aktionen muss auch innerhalb dieses Scopes laufen.

uhuntu

(Themenstarter)
Avatar von uhuntu

Anmeldungsdatum:
19. Februar 2007

Beiträge: 338

Und die Ausgabe soll komplett kommen? Ich glaube, mit sed geht das nicht - oder wird zumindest ziemlich umständlich. Das ist genau das, was mein awk-Skript machen sollte; da war noch ein Fehler, weil found nicht korrekt zurückgesetzt wurde.

Ausgabe brauche ich keine ich muss den Eintrag im File ersetzen. Wenn ich nach deinem Befehl ein > tmp && mv tmp test; echo $? ranhänge dann bekomme ich ja immer noch den Exit Code vom awk Beispiel (lt. meinen Tests?)

Dass zwei mehr als 1x vorkommt oder gar nicht kann eigentlich ausgeschlossen werden? Die Zeile nach zwei besteht auch nur aus foo, nicht etwa auch mal aus xfooy? Was, wenn schon bar1 auf zwei folgt? Auch auszuschließen bzw. auch exit!=0 zurückgeben?

Ein besseres Bsp.: die Einträge bestehen halt aus Paaren z.B.: ich muss jetzt halt nach Server1(eindeutig) suchen und linux z.B. durch windows ersetzen.

1
2
3
4
5
6
7
8
server1
 linux
server2
 linux
server3
 windows
server4
 linux

thx

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17630

1
2
sed '/server1/ {n; s/linux/open-solaris/;}' servers > servers.neu
diff -q servers servers.neu >/dev/null || echo 1

Eine Änderung auf Windows kann ich aus ästhetischen Gründen nicht unterstützen. 😉

Antworten |