Perl正则表达式在cronjob中的奇怪行为

fzsnzjdm  于 2023-05-01  发布在  Perl
关注(0)|答案(2)|浏览(132)

我有这样的文件:

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

因为键“geo40”会导致很多问题,我想删除所有以“geo40=”开头的行。
我尽力了

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

而且效果很好我收到的文件

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

但如果我通过cronjob运行

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

我明白

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

只有键“geo40=”不见了。正则表达式.*$\\n的第二部分似乎被忽略了。
(On命令行,如果我作为用户或root,它可以工作,它可以使用bash或sh)

kqlmhetl

kqlmhetl1#

一种更直接的方法是使用Perl来过滤行,而不是对所有行执行替换。打印所有行,除非它们以字符串geo40=开头:

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

它的标点符号少了很多,你不必担心转义和被插入。
注意,它使用perl -n而不是perl -p

nwo49xxi

nwo49xxi2#

就我个人而言,我怀疑可能会有一些引用的引号,因为您正在将$\\nperl复杂性分层为cron内部find中的单刻度转义。我倾向于尽可能地去除图层,并在有帮助的时候引用。
此外,你做你,但s///感觉像是错误的工具在这里。您要删除该行,而不是编辑该行。也许语义很重要。
toolic's print unless更好,因为它在做你真正想要的事情,但即使这样,它也使用了负数(除非)。
就个人而言,我只使用sed

find /conf/ -type f -name "geometry.*.pas" -exec sed -i '/^geo40=/d' {} ';'

这显然是*删除符合此模式的行 *。
同样,我知道这很常见,但对于这样的事情,我并不是find的粉丝。我知道它可以让你指定像-type f这样的细节,所以有时它是完美的工具,但即使这样,我个人还是喜欢xargs胜过-exec。YMMV。

  • 就个人而言 *,如果我不 * 需要 * -type f之类的东西,我更喜欢globstar,除非列表太长了,它会对你的limits产生问题。
shopt -s globstar; sed -i '/^geo40=/d' /conf/**/geometry.*.pas

这是对sed的一次调用,而不是对每个文件调用一次find(可能还有一次xargs)* 加上 * 一次sed。请注意,您可能需要将其 Package 在带有bash shebang的脚本中。。。或者只是

0 5 * * * bash -c 'shopt -s globstar; sed -i '/^geo40=/d' /conf/**/geometry.*.pas'

就像我之前说的,YMMV。

相关问题