sed -e 's/\([A-Za-z]*\)\( \)\([A-Za-z]*\)\(:\?\)\([A-Za-z]*\)\?\( \)\?\(.*\)\?/[\1][\2][\3][\4][\5][\6][\7]/'

will decorate

class VoxelbuilderAdda:public VoxelBuilder

So it looks like

[class][ ][VoxelbuilderAdda][:][public][ ][VoxelBuilder]

If I instead have

class VoxelBuilder

The output is

[class][ ][VoxelBuilder][][][][]

Is it possible to stop it from printing the empty brackets?

The goal is to print all identifiers with like (square brackets are my simple placeholders but I should have excluded them for the keywords)


and leave keywords (class, struct, public, ...) and separators like ':' as is.

Obviously an inverted pattern for keywords+separator is more beneficial, but I could not figure it out. I actually want

Replace sequence X with \textclassname{X} only if X is not one of

  • class
  • struct
  • union
  • public
  • private
  • protected
  • virtual
  • :
  • ,
  • <
  • >

I have stripped out curly braces and semicolon in an earlier step. The goal would be

class \textclassname{VoxelbuilderAdda}:public \textclassname{VoxelBuilder}

With no inheritance

class \textclassname{VoxelbuilderAdda}

If I had the not operator available, It would not only cover those I have, but any weird multiple inheritance as well.

  • Question: Is your sequence like class, public, … always begin from start of line or other puctuation symbol like :, >, <, …? – Costas Aug 12 '15 at 11:42
  • @Costas The compound type (class,struct,union) is always at the beginning of line. For the rest, assume it is correct C++ syntax. – user877329 Aug 12 '15 at 11:47
  • sed 's/ \(\w*\)/ \\textclassname{\1}/g' – Costas Aug 12 '15 at 11:47
  • @Costas: Almost, but struct \textclassname{Twins}:public \textclassname{std}::pair<T,T> is still wrong. Should have beenstruct \textclassname{Twins}:public \textclassname{std}::\textclassname{pair}<\textclassname{T},\textclassname{T}> – user877329 Aug 12 '15 at 11:50
  • 1
    sed 's/\(::\|[<, ]\)\(\w\+\)/\1\\textclassname{\2}/g' – Costas Aug 12 '15 at 11:58

For such kind of conversion is better to use special parse-tools but if you'd like to operate file like a text try:

sed 's/\(::\|[<, ]\)\(\w\+\)/\1\\textclassname{\2}/g' filename

or use -r option to avoid extra-escaping:

sed -r 's/(::|[<, ])(\w+)/\1\\textclassname{\2}/g' filename
  • Would it be possible to snap the class name (the word after the first white-space) as a sub-expression (so I can generate a label for it) – user877329 Aug 12 '15 at 12:25

so you have to treat spaces, words and colons separately:

sed -e 's/[A-Za-z]\{1,\}/[&]/g' -e 's/:/[&]/g' -e 's/ /[&]/g'

this will replace a) one or more \{1,\} occurences of any letter with the pattern & surrounded by square brackets, b and c) replace a single colon (space) by itself surrounded by square brackets

echo class VoxelbuilderAdda:public VoxelBuilder | sed -e 's/[A-Za-z]\{1,\}/[&]/g' -e 's/:/[&]/g' -e 's/ /[&]/g'
[class][ ][VoxelbuilderAdda][:][public][ ][VoxelBuilder]
  • This is not really correct, I need the keywords "class", "struct", and "public" treated separately. They shall have no additional markup. – user877329 Aug 12 '15 at 11:20
  • please update your question with the desired output. – Fiximan Aug 12 '15 at 11:27
  • s/\w*\|:\| /[&]/g is enough for GNU sed – Costas Aug 12 '15 at 11:36
  • I get that \| mean "OR", but how to understand the \w*? What would be the matches? Is it "greedy word", are numbers excluded, what are the separators? – Fiximan Aug 12 '15 at 11:40
  • 1
    @Fiximan From man grep: "…The symbol \w is a synonym for [_[:alnum:]]…" – Costas Aug 12 '15 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.