1

i have a file like below. I want to search pattern ABC_DATA as a variable and after match, i want to delete from first previous "multipath" line to the line including "}" character. "}" could be after or in the same line with ABC_DATA.

SAMPLE OUTPUT

multipaths {
multipath {
wwid 360000970000267600432533030353944
alias ABC_DATA_11
}
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353946
alias ABC_DATA_12 }

multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}

EXPECTED OUTPUT

multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}
Cyrus
  • 84,225
  • 14
  • 89
  • 153
solmyr
  • 29
  • 3
  • 4
    Welcome to Stack Overflow. [SO is a question and answer page for professional and enthusiast programmers](https://stackoverflow.com/tour). Please add your own code to your question. You are expected to show at least the amount of research you have put into solving this question yourself. – Cyrus Dec 01 '20 at 23:57
  • 1
    Welcome to SO, please do add your efforts in form of code in your question, which is highly encouraged on SO. – RavinderSingh13 Dec 01 '20 at 23:57

3 Answers3

3
$ awk -v RS='multipath\\s*{[^}]*ABC_DATA[^}]*}\\s*(\n|$)' -v ORS= '1' file
multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}
Michael
  • 3,093
  • 7
  • 39
  • 83
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Can you explain this a bit? What is setting `ORS='1'` doing? – dawg Dec 02 '20 at 03:14
  • Thanks Ed, it works :). i will pass ABC_DATA as first argument of bash script. So, awk -v RS='multipath\\s*{[^}]*'$1'[^}]*}\\s*(\n|$)' -v ORS= '1' /etc/multipath.test is final solution for me. – solmyr Dec 02 '20 at 06:14
  • 1
    @Ed Moton. +1. Great regexp: --> remove all unwanted data and `awk` show the `expected output`! – Carlos Pascual Dec 02 '20 at 11:39
  • 1
    @dawg I'm not setting ORS to 1, I'm setting ORS to null so awk doesn't add a newline when outputting each record, and then the `1` at the end is just the usual shorthand for `{print}`. – Ed Morton Dec 02 '20 at 14:22
  • @solmyr make that `RS='multipath\\s*{[^}]*'"$1"'[^}]*}\\s*(\n|$)'` so that `$1` is quoted `"$1"` to avoid globbing, filename expansion, etc. when it's referenced there. – Ed Morton Dec 02 '20 at 14:24
  • 1
    @EdMorton: Head smack. Of course. I was so fixated on `ORS='1'` that I did not notice the space! It is `ORS= '1'` (note space) so that `'1'` is the program... – dawg Dec 02 '20 at 14:33
0

Given your example, you can use this perl:

$ perl -0777 -lpe 's/\bmultipath\h+\{[^{}]*ABC_DATA[^{}]*}\s*//g' file
multipaths {
multipath {
wwid 360000970000267600432533030353945
alias DEF_DATA_11
}
multipath {
wwid 360000970000267600432533030353943
alias DEF_DATA_10
}
}
dawg
  • 98,345
  • 23
  • 131
  • 206
0

Using sed, not really readable but definitely possible:

sed '
   /^multipath {/ {
     :l
     /alias ABC_DATA/ {
       :f
       /}/ d
       N
       b f
     }
     /}/ b
     N
     b l
  }' input

or as a single line:

sed '/^multipath {/{:l; /alias ABC_DATA/{:f /}/d;N;bf};/}/b;N;bl};' input
perreal
  • 94,503
  • 21
  • 155
  • 181