Search code examples
bashperlcron

Strange behavior of Perl regex in cronjob


I have files like:

[grundbild]
geo40=AdnQywADAAAAAAAAAAAAAAAAAt8AAAIVAAAAAAAAAAAAAALfAAACFQAAAAAAAAAAB4AAAAAAAAAAAAAAAt8AAAIV
[MainWindow]
geo40=AdnQywADAAAAAAAXAAAAEQAABrwAAAPwAAAAGAAAADAAAAa7AAAD7wAAAAAAAAAAB4AAAAAYAAAAMAAABrsAAAPv
dockPos40=AAAA/wAAAAD9AAAAAQAAAAAAAACyAAADcfwCAAAAA/sAAAAOAGsAZQB5AGwAYQBiAHMBAAAAOQAAAW4AAAAtAP////sAAAASAHMAdABhAHIAdABtAGUAbgB1AQAAAa0AAAFtAAAAWQD////7AAAAEgBoAGUAbABwAF8AZABvAGMAawEAAAMgAAAAigAAAIoA////AAAF7AAAA3EAAAAEAAAABAAAAAgAAAAI/AAAAAEAAAACAAAABAAAABIAcwBoAG8AcgB0AGMAdQB0AHMBAAAAAP////8AAAAAAAAAAAAAABYAbQBpAG4AaQBkAGUAcwBrAHQAbwBwAQAAADH/////AAAAAAAAAAAAAAASAGgAZQBsAHAAZgB1AG4AYwBzAQAAAKT/////AAAAAAAAAAAAAAAGAG8AYgBpAQAAAR7/////AAAAAAAAAAA=

Because the key "geo40" causes many problems, I want to delete all lines starting with "geo40=" out of the concerning files.

I tried

find /conf/ -type f -name "geometry.*.pas" -exec perl -pi -e 's/^geo40=.*$\\n//' {} ';'

and it works fine. I get files like

[grundbild]
[MainWindow]
dockPos40=AAAA/wAAAAD9AAAAAQAAAAAAAACyAAADcfwCAAAAA/sAAAAOAGsAZQB5AGwAYQBiAHMBAAAAOQAAAW4AAAAtAP////sAAAASAHMAdABhAHIAdABtAGUAbgB1AQAAAa0AAAFtAAAAWQD////7AAAAEgBoAGUAbABwAF8AZABvAGMAawEAAAMgAAAAigAAAIoA////AAAF7AAAA3EAAAAEAAAABAAAAAgAAAAI/AAAAAEAAAACAAAABAAAABIAcwBoAG8AcgB0AGMAdQB0AHMBAAAAAP////8AAAAAAAAAAAAAABYAbQBpAG4AaQBkAGUAcwBrAHQAbwBwAQAAADH/////AAAAAAAAAAAAAAASAGgAZQBsAHAAZgB1AG4AYwBzAQAAAKT/////AAAAAAAAAAAAAAAGAG8AYgBpAQAAAR7/////AAAAAAAAAAA=

But if I run it via cronjob

0 5 * * * find /conf/ -type f -name "geometry.*.pas" -exec perl -pi.cronbak -e 's/^geo40=.*$\\n//' {} ';'

I get

[grundbild]
QywADAAAAAAAAAAAAAAAAAt8AAAIVAAAAAAAAAAAAAALfAAACFQAAAAAAAAAAB4AAAAAAAAAAAAAAAt8AAAIV
[MainWindow]
QywADAAAAAAAXAAAAEQAABrwAAAPwAAAAGAAAADAAAAa7AAAD7wAAAAAAAAAAB4AAAAAYAAAAMAAABrsAAAPv
dockPos40=AAAA/wAAAAD9AAAAAQAAAAAAAACyAAADcfwCAAAAA/sAAAAOAGsAZQB5AGwAYQBiAHMBAAAAOQAAAW4AAAAtAP////sAAAASAHMAdABhAHIAdABtAGUAbgB1AQAAAa0AAAFtAAAAWQD////7AAAAEgBoAGUAbABwAF8AZABvAGMAawEAAAMgAAAAigAAAIoA////AAAF7AAAA3EAAAAEAAAABAAAAAgAAAAI/AAAAAEAAAACAAAABAAAABIAcwBoAG8AcgB0AGMAdQB0AHMBAAAAAP////8AAAAAAAAAAAAAABYAbQBpAG4AaQBkAGUAcwBrAHQAbwBwAQAAADH/////AAAAAAAAAAAAAAASAGgAZQBsAHAAZgB1AG4AYwBzAQAAAKT/////AAAAAAAAAAAAAAAGAG8AYgBpAQAAAR7/////AAAAAAAAAAA=

Only the key "geo40=" is gone. The 2nd part of the regex .*$\\n seems to be ignored.

(On the command line, it works if I act as user or as root, it works by using bash or sh)


Solution

  • A more straightforward approach is to use Perl to filter lines instead of performing a substitution on all lines. Print all lines unless they start with the string geo40=:

    0 5 * * * find /conf/ -type f -name "geometry.*.pas" -exec perl -ni.cronbak -e 'print unless /^geo40=/' {} ';'
    

    It's a lot less punctuation that you don't have to worry about escaping and being interpolated.

    Note that it uses perl -n instead of perl -p.