【发布时间】:2014-05-28 09:41:12
【问题描述】:
考虑如下两个文件。
文件1:
Name : John Paul
Address: 243, First Floor,
XYZ - 12345.
Phone : 555 444 3333
Name : Mison
Address: some address like above
Phone: 444 333 2222
文件2:
Name: John Paul
Address: 243, First Floor,
XYZ - 12345.
Phone: 555 444 3333
我正在使用 Perl。假设我正在从 File2 读取第一个 Name-to-Phone 块并将其存储在 $var_file2 中(通过逐行读取连接)。 File1 的内容存储在$var_file1 (slurped) 中。考虑我需要将 File2 中的整个 Name-to-Phone 块与 File1 中的块进行比较,并将匹配替换为另一个字符串。我在$var_file2 上使用了quotemeta 函数,因为模式匹配不起作用。
$q_var_file2 = quotemeta($var_file2);
$replace = "replace_text";
$var_file1 =~ s/$q_var_file2/$replace/s;
现在,当模式完全匹配时,上面的代码可以完美运行。但在 File1 或 File2 中可能有额外的空格或没有空格,在进行模式匹配和替换时需要忽略这些空格。
我尝试使用仅匹配非空白字符的 \S。但我想我错过了一些东西。我什至尝试使用变量而不在它们上应用quotemeta。
【问题讨论】:
-
我认为您选择了错误的方法。这些字段必须是手动输入的,因此除了空格之外可能会有很多变化。例如,假设您的地址输入为
243 First Floor。然后匹配会因为缺少逗号而失败。甚至会通过输入错误来考虑。您要解决的问题到底是什么?听起来您想通过更改地址来更新数据库? -
@Borodin 确切的问题是非常机密的,抱歉超出了我的权限。这就是为什么我不得不使用类似的问题上下文来解释。实际上,逗号并不重要。只有空格是个问题。我想用另一个替换整个 Name-to-Phone 块,而不仅仅是块中的地址之类的字段。
-
您可能会使用两个额外的变量。将您拥有的两个文本复制到其中,然后在每个文本上执行
s/\s+/ /g。这会将所有空白序列转换为单个空格。然后对这些变量进行匹配。另一种选择是在替换表达式的$q_var_file2(.*?)$q_name部分上执行s/\s+/\\s+/g。替换部分中的$2来自哪里? -
鉴于
$var_file1 =~ s/$q_var_file2/$replace/s,我的想法是更改$q_var_file2的内容,以便将所有空白序列替换为\s+,这将匹配$var_file1中的任意数量的空白。因此s/\s+/\\s+/g将任何空白序列更改为三个字符:反斜杠、小写字母和加号。 -
$var_file2具有在使用quotemeta($var_file2)时不会更改的真实空格。我认为s/\s+/\\s+/g应该应用于$q_var_file2。尝试所有变体。通过这些复杂的操作,您应该在小型数据集上进行测试,并随着代码的执行打印所有值,这样您就可以看到发生了什么以及何时发生。更重要的是,此类打印可让您查看何时发生意外更改以及何时未发生预期更改。 (与print相比,您可能会发现Data::Dump提供了更好的输出。)