Kleines sed-Problem

U

upperlimit

Jungspund
Hallo,

ich bin gerade dabei, meine sed-Kenntnisse aufzubessern. Dabei stiess ich auf folgendes Problem.

In einer (cpp)-Datei waren alle Kommentare mit // eingeleitet, bis auf eine einzelne Zeile. Um Konsistenz in dieser Quelle herzustellen, benutzte ich nun sed, um aus der //-Zeile eine /*...*/-Zeile zu machen, also beispielsweise

// Transformation method

wird zu

/* Transformation method */

Dieses erreichte ich mit folgender sed-Zeile:

sed '{152s/\/\//\/\*/;152s/$/\*\//}' datei
(Die Idee, sed zu benutzen, waehlte ich, da ich noch andere Dateien gleichen Typs derart behandeln muss.)

Das Problem ist nun, dass ich fuer die Zukunft nicht sicher sein kann, dass dieser //-Kommentar ausschliesslich in Zeile 152 vorkommen kann (es arbeiten noch andere Kollegen an dieser und aehnlichen Dateien).

Daher ist meine Frage, wie ich den sed-Aufruf verallgemeinern kann, sodass jeder Zeile, die mit // beginnt, das // durch /* ersetzt wird und am Ende dieser Zeile ein */ angehaengt wird (ohne die genaue Zeilennummer zu kennen).

Vielen Dank und Gruesse,
upperlimit
 
Muss es unbedingt sed sein?

Gruss, Xanti

edit: Hier eine Lösung mit perl:

Code:
perl -pi -e 'if (/\/\//) {s!//!/*!; s!$!*/!}' file
 
Zuletzt bearbeitet:
Hallo Xanti,

muss nicht, aber ein perl-Einzeiler erhoeht nun nicht gerade meine Kenntnisse ueber sed.:rolleyes:

Dennoch, Danke fuer Deine schnelle Antwort.

Gruss,
upperlimit
 
Hallo

Code:
$ cat test
//test1
test2
//test3

$ sed -e '/^\/\//s!^//\(.*\)$!/*\1*/!g' test
/*test1*/
test2
/*test3*/

;)
Gruß Wolfgang
 
Code:
sed -e '/\/\//s/\/\//\/*/;/\/\*/s/$/*\//' file

edit: Ups, Wolfgang war schneller. Egal :)
 
Hallo,

danke nochmals fuer die Antworten.

Allerdings musste ich feststellen, dass die Loesung von Wolfgang mein Problem nicht geloest hat; funktionieren tut nur der Code von Xanti (Warum?)

upperlimit
 
Das kommt wahrscheinlich auf das sed und Dein OS an. Kommen Fehlermeldungen? Diese bitte auch angeben.

Bei mir funktioniert übrigens Wolfgangs Lösung.

Noch mal zum Verständnis:

Wolfgang testet auf //, merkt sich den Rest der Zeile (in \1) und ersetzt diese Zeile dann durch das Gemerkte, eingerahmt in /* und */.

Ich geh da trivialer ran. Ich teste erst auf //, ersetze dieses durch /* und teste anschliessend dieselbe Zeile auf /* und ersetze dann das Zeilenende durch */. Dies ist umständlich, leider kenn ich keine Gruppierung in sed, damit nur einmal getestet wird. Im Sinne von:

Code:
/\/\//{s/\/\//\/*/;s/$/*\//}

Vielleicht weiss Wolfgang, wie man in sed Befehle gruppiert.

edit: Vielleicht kommt Dein sed nicht mit "s!..!..!" klar. *vermut*
 
Zuletzt bearbeitet:
Hallo
Wenn Leerzeichen oder tab davor und nachfolgende // in der Zeile ignoriert werden sollen, dann ist folgendes genauer.
Code:
$ cat test
//test1
test2
//test3
/test4
 //test5
 test6/
 test7//
$ sed -e 's!^[ \t]*//\(.*\)$!/*\1*/!g' test
/*test1*/
test2
/*test3*/
/test4
/*test5*/
 test6/
 test7//

Gruß Wolfgang
 
Das ist es, Wolfgang !

Ich habe eben erst festgestellt, dass mir die Loesung von Xanti am Ende jeder Zeile die mit einem /* beginnt, ein zusaetzliches */ an das Ende dieser Zeile hinzufuegt, also

// Transformation method

wird zu

/* Transformation method */ ,
aber

} /* end mdlOutput */

wird zu

} /* end mdlOutput */*/ .

upperlimit
 
Sorry, hab die Beiträge zwischendurch nicht gesehen, und schon abgedrückt. ;)

Xanti schrieb:
Dies ist umständlich, leider kenn ich keine Gruppierung in sed, damit nur einmal getestet wird. Im Sinne von:

Code:
/\/\//{s/\/\//\/*/;s/$/*\//}

Vielleicht weiss Wolfgang, wie man in sed Befehle gruppiert.
Genau so geht es.:)
edit: Vielleicht kommt Dein sed nicht mit "s!..!..!" klar. *vermut*

In meinem ersten Beitrag matche ich auf // am Beginn der Zeile.
Wenn erfüllt, ersetze ich alles was nach den // kommt mit /*<gefunden>*/

Wenn dein sed ! nicht als Begrenzer versteht, dann nimm / und escape die Slash.
Code:
$ sed -e 's/^[ \t]*\/\/\(.*\)$/\/*\1*\//g' test

Gruß Wolfgang
 
upperlimit schrieb:
Das ist es, Wolfgang !

Ich habe eben erst festgestellt, dass mir die Loesung von Xanti am Ende jeder Zeile die mit einem /* beginnt, ein zusaetzliches */ an das Ende dieser Zeile hinzufuegt, also

Stimmt, das hab ich nicht berücksichtigt. Wenn man die Substitutionen vertauscht, sollte es gehen

Code:
sed -e '/\/\//s!$!*/!;/\/\//s!//!/*!' file

Wolfgang schrieb:
Genau so geht es.

Bei mir nicht: ?(

Code:
[test]$ sed -e '/\/\//{s!$!*/!;s!//!/*!}' file
sed: 1: "/\/\//{s!$!*/!;s!//!/*!}
": bad flag in substitute command: '}'

OS ist FreeBSD 6.1

Gruss, Xanti
 
Bei mir geht es jetzt auch mit

sed -e '/\/\//s/$/*\//;/\/\//s/\/\//\/*/' file

einziger (sichtbarer) Unterschied zur Loesung von Wolfgang: die relevante Zeile

/* Transformation method */

wird nicht mehr eingerueckt (bevorzugt).

Gruss, upperlimit
 
Hallo

Bei mir nicht: ?(
Xanti schrieb:
Code:
[test]$ sed -e '/\/\//{s!$!*/!;s!//!/*!}' file
sed: 1: "/\/\//{s!$!*/!;s!//!/*!}
": bad flag in substitute command: '}'

OS ist FreeBSD 6.1

Gruss, Xanti

Sorry, habe kein FreeBSD hier zum Testen.
Aber hab mal nachgesehen und folgendes gefunden:
...
Two of the functions take a function-list. This is a list of sed func-
tions separated by newlines, as follows:

{ function
function
...
function
}

The ``{'' can be preceded by white space and can be followed by white
space. The function can be preceded by white space. The terminating
``}'' must be preceded by a newline or optional white space.
...
Quelle
IMHO solltest du die Semikola einfach durch Leerzeichen ersetzen.
Teste mal, ob das so geht.

Gruß Wolfgang
 
Hmm, geht leider auch nicht.

Code:
[test]$ sed -e '/\/\//{ s!$!*/! s!//!/*! }' file
sed: 1: "/\/\//{ s!$!*/! s!//!/* ...": bad flag in substitute command: 's'

Geht es unter Linux?

Gruss, Xanti
 
Xanti schrieb:
Hmm, geht leider auch nicht.

Code:
[test]$ sed -e '/\/\//{ s!$!*/! s!//!/*! }' file
sed: 1: "/\/\//{ s!$!*/! s!//!/* ...": bad flag in substitute command: 's'

Geht es unter Linux?

Gruss, Xanti
Nein latürnich nicht. ;)
Ich denke aber, dass es an deiner Version von sed liegt.

$ sed --version
GNU sed Version 4.1.4
Copyright (C) 2003 Free Software Foundation, Inc.

Was hast du für eine Version, und was steht in deiner Manpage zu Function-list?
Eventuell geht das nur mit der Option -f Scriptname -> also aus einem Sedscript heraus mit Newline. ?!

Mit *BSD habe ich keine Erfahrung.

Gruß Wolfgang
 
Wolfgang schrieb:
Nein latürnich nicht. ;)

Nagut, da will ich Dir mal glauben ;)

Wolfgang schrieb:
Ich denke aber, dass es an deiner Version von sed liegt.
...
Was hast du für eine Version, und was steht in deiner Manpage zu Function-list?
Eventuell geht das nur mit der Option -f Scriptname -> also aus einem Sedscript heraus mit Newline. ?!

Mit *BSD habe ich keine Erfahrung.

Gruß Wolfgang

Das seltsame ist, dass Dein Quote aus der man-Page übereinstimmt mit der unter FreeBSD. Die Versionsnummer unter FreeBSD herauszubekommen ist etwas kompliziert. Naja, ist ja auch egal, brauchen tue ichs nicht wirklich, da ich für sowas perl nehme.

Gruss, Xanti
 
Ist wirklich seltsam, leider kann ich das nicht testen.
Aber ich habe noch etwas in einem alten Newsgoupeintrag gefunden, was so ein Konstrukt zulässt, also mit Newline pro Befehl.
$ sed -e '/^$/{
> N
> /^\n$/D
> }' /tmp/test
Also ohne Semikola.

Frage mich nur, warum das Problem bei freeBSD - Sedusern so selten auftaucht.:think:
Entweder die sind alle sed-Genies, oder nutzen sed nicht. :devil:

Gruß Wolfgang
 
Yep, mit den Zeilenumbrüchen funktioniert's. Schon seltsam. Vielleicht ist mein sed kaputt. Vielleicht kann ja ein anderer FreeBSD-Nutzer testen, ob's bei ihm funktioniert. :)

Gruss, Xanti
 
Xanti schrieb:
Yep, mit den Zeilenumbrüchen funktioniert's. Schon seltsam. Vielleicht ist mein sed kaputt. Vielleicht kann ja ein anderer FreeBSD-Nutzer testen, ob's bei ihm funktioniert. :)

Gruss, Xanti


Denke nicht, dass dein sed kaputt ist, war mir nur fremd, dass unter *BSD die Shell eine Newline durchgehen lässt. (was sie unter Linux auch nicht tut!)
Insofern stimmt die Manpage ja schon.

Na dann hätten wir das ja geklärt, und ich kann wieder ruhig schlafen, ohne freeBSD installieren zu müssen. :D

Gruß Wolfgang
 
Zurück
Oben