Search code examples
regexgrepmultiline

How to match a pattern with unrelated charaters/blank-space between two fixed strings?


I'm trying to match a string in my files which begins with imports: [ and does not contain SharedModule. It can have any number or spaces, line-breaks, or other characters (words) in between the two strings. I've been trying to do find those with:

grep 'imports: \[[.*\s*]*SharedModule' */*.module.ts

but I cannot even find the files which have 'SharedModule' in it. My thought process was that .* would find any words and \s would find blank space characters, and the character class with * selector would allow this to show up in any order.

  1. Can I use character classes like this to skip a variable number of unrelated lines/characters?
  2. How do I negate the statement so it returns lines without 'SharedModule'?
  3. The goal is to append 'SharedModule' to the import array wherever it does not already exist.

Thanks! (I'm new to this and the one thing I've learned so far is: regular expressions are hard)

SAMPLE MATCH:

imports: [
  IonicPageModule.forChild(FormPage),
  DynamicFormComponentModule,
  SharedModule
],

should not match but

imports: [
  IonicPageModule.forChild(LeadershipPage),
],

should.


Solution

  • grep doesn't process multiline strings by default. This is available with gnu grep with -z option but then regex will be a bit more complex.

    You may be better off using gnu awk solution with custom RS (record separator):

    awk -v RS='imports:[[:blank:]]*\\[[^]]*\\],[[:space:]]+' 'RT !~ /SharedModule/{ORS=RT} 1' file
    
    imports: [
      IonicPageModule.forChild(LeadershipPage),
    ],
    

    Where file content is this:

    cat file
    imports: [
      IonicPageModule.forChild(FormPage),
      DynamicFormComponentModule,
      SharedModule
    ],
    
    imports: [
      IonicPageModule.forChild(LeadershipPage),
    ],