【问题标题】:find: missing argument to `-exec' in perl script查找:在 perl 脚本中缺少 `-exec' 的参数
【发布时间】:2012-01-30 06:06:18
【问题描述】:

我知道有很多类似我的小问题的问题。一些被第二个-exec修复了,但这不是我需要的。也许我只是没有看到我的问题到底出在哪里......

我想在我的博客分析输出中匿名化 html 文件中的所有 IP:

#!/usr/bin/perl
use warnings;
use strict;
use readPathsFromConf;

system ("find $readPathsFromConf::WWWPATH$readPathsFromConf::WWWSUBDIR -type f -name \"\*\" -exec sed -i '' 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/anonymisiert/g' \{\} \;");

我只得到

find: missing argument to `-exec'

当我在命令行上键入时,我在 STDOUT 上得到了正确的文件:

find /var/www/statistics/ -type f -name "*"

但是一旦我添加了执行部分,我就会得到错误。

转义字符有问题吗? 我错过了什么? (请原谅我的英语)

【问题讨论】:

  • 在这种情况下,如果您必须像这样使用find,请在* 周围使用单引号。还可以考虑将命令拆分为数组 (my @cmd = ( "find", "/var/www/statistics/", "-type", "-f", "-name", "*", "-exec", ...);) 中的命令和参数,然后使用 system @cmd;。这样可以避免运行 shell 来运行命令。
  • 为什么将 * 放在单引号而不是双引号中? Shell 不会扩展其中任何一个中的 glob。

标签: perl shell sed replace


【解决方案1】:

这应该可以 -

#!/usr/bin/perl

use warnings;
use strict;

system ("find /var/www/statistics/ -type f -name \"*\" -exec sed -i 's/\\([0-9]\\{1,3\\}\\.\\)\\{3\\}[0-9]\\{1,3\\}/anonymousIP/g' {} +");

【讨论】:

  • 我认为你也需要转义反斜杠。
  • 反斜杠已经用于转义相应的后续字符 - 我认为我不应该再次转义它们
  • 不,@AdamZalcman 是对的,您需要再次逃脱它们。
  • 但我错了 - 这正是它不起作用的原因 - 已解决 - 感谢您的帮助!
  • 嗨 Jaypal,我把“绿钩”给了 Adam - 你可以吗?
【解决方案2】:

您应该转义嵌入在字符串中的引号和反斜杠:

system ("find /var/www/statistics/ -type f -name \"*\" -exec sed -i 's/\\([0-9]\\{1,3\\}\\.\\)\\{3\\}[0-9]\\{1,3\\}/anonymousIP/g' {} \\;");

另外,请注意,在某些平台(例如 Mac OS X)上,sed 的 -i 选项需要一个参数 - 备份文件扩展名。

【讨论】:

  • GNU sed 不需要带有-i 选项的参数,但我同意,我的mac 度过了最艰难的时光,因为它不允许我在没有备份参数的情况下使用-i 选项.
  • 我对 sed 的实现很满意 -i 没有参数(不创建备份)。如果我想提供一个参数,它不能与-i 用空格分隔。版本:GNU sed 4.1.5
  • 谢谢,伙计们。我也在mac上试过。相应地编辑了我的答案。
  • 不客气。 mac 上sed 的默认版本是BSD,它的功能并不丰富。我下载了GNU sed 4.2,它更灵活。如果您想下载GNU version,请从here 下载它并使用./configure --prefix=/usr/local/bin make sudo make install 构建它。您将需要开发人员工具,因为我们需要 make,而 mac 也没有。下载后,您可以将旧的 sed 重命名为 _sed。我有两个 - [jaypal:~/Temp] which _sed /usr/bin/_sed [jaypal:~/Temp] which sed /usr/local/bin/sed
  • 反斜杠已经用于转义相应的后续字符 - 我认为我不应该再次转义它们
【解决方案3】:

Perl 有一个非常好的File::Find 核心模块。无需调用外部实用程序即可使用 find

甚至还有一个名为 find2perl 的帮助脚本,它可以帮助您从使用 shell 的 find 到 Perl 的过渡。这在上面的链接中进行了讨论。

【讨论】:

  • 是的,我也会尝试的。我想我在应该使用 perl 模块的地方经常使用 system、exec 或 qx。但我对编程和 Perl 还是很陌生——我会解决这个问题的……谢谢你的帮助!
【解决方案4】:

因为在:

system ("find /var/www/statistics/ -type f -name "*" -exec sed -i 's/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/anonymousIP/g' {} \;");

星号周围的双引号不会被转义。所以,解释器认为你将两个东西相乘,并且会自动将每个字符串转换为0(顺便说一句,这也是你在 Perl 中不使用== 进行字符串比较的原因)。

例如,单线

perl -e 'use strict;use warnings;my $a="abc";my $b="def";my $c=$a*$b;print "$c\n";'

产生输出

Argument "def" isn't numeric in multiplication (*) at -e line 1.
Argument "abc" isn't numeric in multiplication (*) at -e line 1.
0

由于您启用了strictwarnings,您也应该看到与上面给出的类似警告。

然而,更重要的是:如果您的脚本包含一个 system 调用,为什么不直接在命令行上运行 system 的参数?

【讨论】:

  • 我很抱歉 - 我发布了一个旧版本:我已经发现了关于转义星号的信息。我使用 perl 脚本来获取路径的变量 - 我已经为我的帖子插入了它们以保持简单。我在帖子中更正了它。
  • 好的,在这种情况下,只需将星号周围的双引号转义(或用单引号替换它们),你应该很高兴。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 2014-04-05
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 2019-06-22
  • 2017-12-16
相关资源
最近更新 更多