2011-12-29 56 views
3

我知道有很多类似于我的小问题的问题。有几个被第二个执行程序修复了,但那不是我需要的。也许我只是没有看到这里我的问题真的是......发现:在perl脚本中缺少参数到`-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 "*" 

但我添加exec部分我得到错误。

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

+0

在这种情况下,如果你必须执行'find'这样,周围使用'*'单引号。还可以考虑将命令分解为数组中的命令和参数('my @cmd =(“find”,“/ var/www/statistics /”,“-type”,“-f”,“-name”,“ *“,”-exec“,...);'),然后使用'system @cmd;'。这可以避免运行一个shell来运行该命令。 – 2011-12-29 22:55:18

+0

为什么把*换成单引号而不是双引号?壳牌公司并没有扩大其中的任何一个。 – 2011-12-29 23:27:34

回答

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选项需要一个参数 - 备份文件扩展名。

+0

'GNU sed'不需要'-i'选项的参数,但我同意,我用'mac'最难过,因为它从未允许我使用没有备份参数的'-i'选项。 – 2011-12-29 22:56:51

+0

我的sed实现对-i没有参数感到满意(创建没有备份)。如果我想提供一个参数,它不能与'-i'空格分开。版本:GNU sed 4.1.5 – choroba 2011-12-29 22:57:48

+0

谢谢,伙计们。我也在Mac上尝试过。相应地编辑我的答案。 – 2011-12-29 23:03:15

1

因为:

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

+0

我很抱歉 - 我发布了一个旧版本:我已经发现了关于逃脱星号。我使用perl脚本来获取我的路径变量 - 我已经为我的帖子插入了它们以保持简单。 我在我的文章中纠正了它。 – user982809 2011-12-29 22:56:36

+0

好的,在这种情况下,只是绕着星号的双引号(或用单引号替换它们),你应该很好走。 – 2011-12-29 23:02:28

+0

做到了。没有改变。 – user982809 2011-12-29 23:20:17

3

Perl有一个非常好的File::Find核心模块。没有必要调用外部工具来使用找到

甚至有一个名为的帮手脚本find2perl这可能会帮助您从使用shell的find到Perl的桥梁。这在上面的链接中讨论。

+0

是的,我也会尝试。我认为我经常在使用perl模块的地方使用system,exec或qx。但是,我对编程和Perl还是比较陌生的 - 我会得到这个...感谢您的帮助! – user982809 2011-12-29 23:25:33

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' {} +"); 
+0

我认为你也需要逃避反斜杠。 – 2011-12-29 23:05:22

+0

哎呀,谢谢Adam,你绝对正确。固定! :) – 2011-12-29 23:16:43

+0

反斜杠已经意味着要逃避相应的下面的字符 - 我想我不应该再次逃脱它们 – user982809 2011-12-29 23:19:05