1

How do I match a multiple line string in a file like

# custom prompt
aa=`command1 arg1 arg2`
bb=`command2 arg3 arg4`
PS1="$aa$bb"
# custom prompt

I am using this

perl -0pe 's/# custom prompt\n.*\n.*\n.*\n# custom prompt\n//gm' -i .bashrc

I want to delete all the lines between # custom prompt ~ # custom prompt (including the # custom prompt lines). But the one liner works only for 5 lines cases. Is there a way to match arbitrary multiple lines with new lines like (this does not work)

perl -0pe 's/# custom prompt[\n.]+# custom prompt\n//gm' -i .bashrc
Jihyun
  • 883
  • 5
  • 17

2 Answers2

2

Removing lines:

perl -i -0pe 's/# custom prompt.*?# custom prompt\s*\n//s' .bashrc

or with anchors

perl -i -0pe 's/^# custom prompt.*^# custom prompt\n//sm' .bashrc
#                                                      ^
#                                               needed m modifier

.*? is the no-greedy way to write .*.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • I didn't know gm option was not necessary. Your command worked perfectly. Thank you – Jihyun Feb 02 '23 at 19:32
  • @Jihyun Comments: 1) `/g` means to do it "globally", so for the whole string. So if these prompt-sections repeat through the file, you _do_ need `/g`. But then you need to limit `.*` to stop at the first `# custom` pattern, so it should be `.*?# custom` (etc). 2) `/m` is so that the string is treated as a Multiline one, in the sense taht `^` and `$` match start/end of lines inside the string as well (not only the first and the last). You don' t need that. 3) Finally, `/s` makes the `.` pattern match newlines as well – zdim Feb 02 '23 at 19:44
0

While this isn't "in-place" per se, it's more straight forward than having to increment tracking counters, while also allowing for existence of blank lines in between the 2 # command prompt's :

assumptions :


there are exactly 2 # command prompt's in the input - no more, no less

nothing before the 1st # command prompt

printf '%s\n' '# custom prompt
               aa=`command1 arg1 arg2`
               bb=`command2 arg3 arg4`
               PS1="$aa$bb"
               cc=`command3 arg5 arg6`

               dd=`command4 arg7 arg8`
               # custom prompt
               PS2="$bb$aa"'                                          | 

gtee >( gcat -n | mawk 'BEGIN { print } END { print RS } !_' >&2; )   | 
{m,g,n}awk '($!NF = $NF)^_' FS='[#] custom prompt\n' RS='^$' ORS= | 
gcat -b | mawk 'BEGIN { print (_="---- AFTER ----") } END { print (_)"\n" } _'

     1  # custom prompt
     2  aa=`command1 arg1 arg2`
     3  bb=`command2 arg3 arg4`
     4  PS1="$aa$bb"
     5  cc=`command3 arg5 arg6`
     6  
     7  dd=`command4 arg7 arg8`
     8  # custom prompt
     9  PS2="$bb$aa"


---- AFTER ----
     1  PS2="$bb$aa"
---- AFTER ----
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11