0

Am not quite familiar with bash coding. I have a cpp file

#include <lib1.h>
#include <ccLib1.h>
#include <anotherlib.h>
#include <ccToto.h>

How to make a script that would automatically replace <cc*.h> with "*.h"; replacing only those that start with cc?

I tried something like sed -i -e 's/cc*>/"/g' file.cpp

Courier
  • 888
  • 2
  • 11
  • 30
  • `sed` behaves the same way invoked from any shell, or with no shell at all; moreover, it's a tool provided by your operating system, not your shell. There's nothing bash-specific here. – Charles Duffy Jun 10 '16 at 04:39
  • We have some answers already , only the specification is a bit late - not unusual in practice ;-) could you provide some further details. 1) shall the transforms leave the angle brackets intact? (I think yes not quotes instead) 2) Shall ``be left as is (I think yes, otherwise invalid). – Dilettant Jun 10 '16 at 04:44
  • @Dilettant, the OP clarified the transform to quotes on a comment to Cyrus's answer. Quotes have a distinct semantic meaning in C preprocessor syntax, and it's one that makes sense in this context. – Charles Duffy Jun 10 '16 at 04:45
  • That is why I edited the question for making this explicit, it is in the review queue ... – Dilettant Jun 10 '16 at 06:28

3 Answers3

5

With GNU sed:

sed '/^#include/{s/<cc\(.*\.h\)>/"\1"/;}' file

Output:

#include <lib1.h>
#include "Lib1.h"
#include <anotherlib.h>
#include "Toto.h"

See: The Stack Overflow Regular Expressions FAQ

Community
  • 1
  • 1
Cyrus
  • 69,405
  • 13
  • 65
  • 117
  • but also need to be replaced with "*" – Courier Jun 10 '16 at 04:44
  • 1
    @polar, it should be doing that replacement now (as-edited), unless you want to do that even in things that don't start with `cc` -- if that's the case, the question could stand to be edited to be made more clear. – Charles Duffy Jun 10 '16 at 04:47
  • As it stands currently, on my sed it bails out with `sed: 1: "/^#include/{s/ – Dilettant Jun 10 '16 at 04:54
  • 1
    @Dilettant Try adding a tactical semicolon inside the braces. `/^#include/{;s/.../.../;}` ... though syntactically, the braces are completely superfluous here. – tripleee Jun 10 '16 at 04:57
  • @Dilettant: I've added a `;`. Thank you tripleee. – Cyrus Jun 10 '16 at 04:59
  • @tripleee thanks. On my machine `sed '/^#include/{;s//"\1"/;}' file.cpp`now works. I know why I edit these sed oneliners only time boxed ... and with the help of my friends (8) ... – Dilettant Jun 10 '16 at 04:59
  • So just to make it explicit, the expression could be simplified to `sed '/^#include/s/]*\.h\)>/"\1"/' file` -- note also the slightly improved wildcard to avoid straddling a broket boundary (unlikely in well-formed C but why take chances). – tripleee Jun 10 '16 at 05:01
  • but it worked for me only after adding -i -e: `sed -e -i ...` – Courier Jun 10 '16 at 05:21
  • @Cyrus Also please how to deal with slash (/) with sed? – Courier Jun 10 '16 at 05:42
  • 1
    @polar: If you want to search `/` escape it: `\/`. – Cyrus Jun 10 '16 at 05:52
0
sed 's/^#include\ \(<cc\|<\)\(.*\)\.h>/#include "\2\.h"/g' so_file.cpp
gzh
  • 3,029
  • 1
  • 14
  • 20
  • Well, hm `\2` not defined in the RE is what the sed on my machine tells me when I try that answer. My eyes see the 2nd pair of parentheses, but ... the machine does not. – Dilettant Jun 10 '16 at 05:02
  • @Dilettant, sorry, I missed some escape character. I have revised it. – gzh Jun 10 '16 at 05:14
  • No error, good, ... but now it does not change anything i.e. `` and `` from sample data are simply passed as they are. – Dilettant Jun 10 '16 at 05:33
  • @Dilettant, on my pc, will be converted to "Lib1.h". – gzh Jun 10 '16 at 05:39
  • That is why I ony approach these sed/pattern tasks time boxed, so that I have time left to use python or the like in case I need portability ;-) Thanks for the re-tests and edits. – Dilettant Jun 10 '16 at 05:52
0

For complete solutions of the amended / updated question cf. the answer of @Cyrus on this page together with the comments for eventual portability tricks. It additionally

  1. anchors the stream edit expression on ^#include and
  2. transforms from <...> to "..."in the matching cases.

A simple context free solution without the later explicated transform to a different search path includes (from <ccHeader,h> to "Header.h")

$> sed  's/<cc\(..*\.h>\)/<\1/g' so_file.cpp

#include <lib1.h>
#include <Lib1.h>
#include <anotherlib.h>
#include <Toto.h>

sed does on my machines not like the notion of at least one any character via .+ so I simply give it ..* without discussing further ;-)

You will want at least a character for the basename of the header, so a cc.h would be left intact.

Dilettant
  • 2,962
  • 3
  • 25
  • 27
  • OP says they want `"*.h"` in output. The literal quotes are probably a legitimate part of that (meaning the headers are expected to be in the source directory, not in the standard-include search path). Thus, it would be `#include "Lib1.h"` – Charles Duffy Jun 10 '16 at 04:41
  • As usual spec is far behind implementation - I asked in comment to question. In the case you suggest to also consider, There would be additional info in question helpful and needed. As it stands I think this answer is as good as it gets ... when I suggest sed patterns ;-) – Dilettant Jun 10 '16 at 04:46