
Ich versuche beispielsweise, Felder aus einer Struktur zu extrahieren.
typedef struct newstruct {
long id;
uint32_t vtid;
struct HN* next;
} HashNode;
Ich möchte sed/awk verwenden, um den Strukturnamen zu extrahieren, gefolgt von den Feldern mit einem Trennzeichen als
newstruct HashNode: long id, uint_32 vtid, struct HN* next
Antwort1
Mit ist es ziemlich unkompliziert und awk
mit vielleicht machbar sed
.
Mit awk
hätten Sie einen Status, der in jeder typedef
Zeile gesetzt/zurückgesetzt wird und in jeder Zeile mit einer rechten geschweiften Klammer endet. Ein geeignetes awk
Skript würde so aussehen
BEGIN {
state = 0;
typedef="";
fields="";
}
/typedef[ ]+struct/{
state = 1;
typedef=$3;
next;
}
/}.*;/ {
if (state != 0) {
sub("^.*}[ ]*","",$0);
sub(";","",$0);
sub(",$","",fields);
printf "%s %s: %s\n", typedef, $0, fields;
state = 0;
fields = "";
typedef = "";
}
next;
}
(state == 1){
gsub("[ ]+"," ", $0);
gsub(";",",",$0);
fields = fields $0;
next;
}
wobei die Klammern [
und ]
ein Leerzeichen und einen Tabulator einschließen (um es portierbar zu machen). Das Skript besteht aus vier Teilen:
- die
BEGIN
Aktion initialisiert Variablen (nicht unbedingt notwendig, aber einige Awks machen mit nicht initialisierten Variablen leicht unterschiedliche Dinge) - das Muster, das der Zeile mit entspricht
typedef
, gefolgt von Leerzeichen und dem Wortstruct
. Dabei werden mindestens 3 Felder in der Zeile erwartet, wobei das dritte als Name des Typdefinitions verwendet wird. - ein Muster, das der schließenden geschweiften Klammer entspricht. Nur für den Fall, dass Ihre Datei andere Dinge enthält, prüft die Aktion, ob
state
sie gesetzt wurde. Dies$0
ist die aktuelle Zeile. Die erste Ersetzung entfernt alles vor dem Wort, an dem wir interessiert sind, und die zweite entfernt das darauf folgende Semikolon. Die dritte Ersetzung ändert ein Komma nach derfields
Variable, die aus der vierten Aktion (unten) stammt, in eine leere Zeichenfolge. - ein Muster, das mit allen anderen Zeilen übereinstimmtWann
state
gesetzt ist. Wie bei der vorherigen Aktion wird hier durch Ersetzung die nicht gewünschte Teilmenge entfernt, indem zunächst mehrere Leerzeichen auf ein einziges Leerzeichen reduziert werden und dann das abschließende Semikolon in ein Komma geändert wird.
Rufen Sie diese Datei foo.awk
und Ihre Eingabedaten auf foo.in
, um awk wie folgt zu verwenden:
awk -f foo.awk <foo.in
Wenn Sie Zeilen wie diese abgleichen möchten:
struct foo {
statt
typedef struct foo {
dann könnte das Muster geschrieben werden
/^([ ]*typedef)?[ ]+struct[ ]+/{
(wiederum mit einem wörtlichen Leerzeichen und einem Tabulator in den eckigen Klammern). Die Klammern markieren einGruppeund das Fragezeichen ?
bedeutet, dass dies null- oder mehrmals wiederholt werden soll. (Die{
auf der Linie bezeichnet eigentlich den Beginn derAktion, aber ich habe es dort gelassen, damit es mit der Zeile im angegebenen Skript übereinstimmt).
Weiterführende Literatur:
Antwort2
sed -rn '
/typedef struct ([[:alnum:]_]+)\s+\{/!b
s//\1/; h
:X
n
/}\s+([[:alnum:]_]+)/{
s//\1/
H
g
s/;//g
s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/\1 \5: \2, \3, \4/
p;b
}
s/\s*(.+);\s*/\1/
H
bX
' file
newstruct HashNode: long id, uint32_t vtid, struct HN* next