从INI文件中查找包含空格且没有空格的字符串

时间:2017-06-19 10:22:49

标签: regex perl

我的输入*INI文件:

\nleftarrow = {\not\leftarrow}
\nrightarrow = {\not\rightarrow}
\nleftrightarrow = {\not\leftrightarrow}

我需要找到\not\leftarrow并替换为字符串\nleftarrow。事情就在这里\not\leftarrow我们需要检查查找字符串中是否有空格,例如:\not \leftarrow。我们需要替换字符串的两件事。

在主文件中:

 $str=~s/\\not\\leftarrow/\\nleftarrow/g;
 $str=~s/\\not \\leftarrow/\\nleftarrow/g;

我的代码:

foreach my $repStr(@tags) #storing all the `*INI` lines in the Array
{
    my ($findStr, $replaceStr) = ($repStr =~ /^([^\s]*)\s*=\s*\{([^\{\}]*)\}/i);
    $str=~s/$replaceStr/$findStr/g;

    #I need to check the string with space

}

任何人都可以指导我对代码进行编码的方式。

2 个答案:

答案 0 :(得分:1)

您可以使用命令组合创建单个命令数组:my @cmds = $replaceStr =~ /\\[^\\]+/g。然后使用两者之间的可选空格加入它们:join '\s*', @cmds 但是,您还需要转义$replaceStr的特殊字符(如反斜杠),否则它们会在正则表达式中打扰您。您可以使用quotemeta内置功能执行此操作。 (也可以使用\Q...\E在正则表达式内部完成此操作,但由于此处您不希望转义\s*quotemeta会更方便。

放在一起,它变成了:

my @cmds = $replaceStr =~ /\\[^\\]+/g
my @esc_cmds = map { quotemeta } @cmds;
my $re = join '\s*', @esc_cmds;

但是你可以将它组合成一行(如果它对你来说足够可读):

my $re = join '\s*', map { quotemeta } ($replaceStr =~ /\\[^\\]+/g);

例如,此脚本以您希望的方式工作:

use strict;
use warnings;
use feature 'say';

my @tags = ( '\nleftarrow = {\not\leftarrow}',
             '\nrightarrow = {\not\rightarrow}',
             '\nleftrightarrow = {\not\leftrightarrow}' );

# Only the last 2 lines should be left unchanged
my $str = '\not\leftarrow
\not \leftarrow
 \not\leftarrow
\ not\leftarrow
\leftarrow';

say "Before:\n$str";
foreach my $repStr(@tags) {
    my ($findStr, $replaceStr) = ($repStr =~ /^([^\s]*)\s*=\s*\{([^\{\}]*)\}/i);

    my $re = join '\s*', map { quotemeta } ($replaceStr =~ /\\[^\\]+/g);

    $str =~ s/$re/$findStr/g;
}
say "\nAfter:\n$str";

答案 1 :(得分:1)

为了解决问题,我们给出了以下内容:

配置文件

这将TeX / LaTeX宏名称映射到TeX / LaTeX命令序列。它是macro name = command sequence格式。 E.g:

\nleftarrow = {\not\leftarrow}
\nrightarrow = {\not\rightarrow}
\nleftrightarrow = {\not\leftrightarrow}

不清楚包含替换的括号是什么功能。它们是否出现在源文件中(见下文)?或者,他们划分空格吗?简而言之,他们应该被剥夺吗?

如果您只提供一段示例文本而不是要求我们对其进行假设,情况会好得多。

TeX / LaTeX源文件

在此,有一些命令序列需要根据上述配置文件中的映射用宏名称替换。但是,because TeX eats spaces after macro invocations,需要考虑替换序列中每个命令之间空格字符的可能性。在上面的例子中,每个替换序列中只有两个命令,但不难想象更多。

如果您只提供一段示例文本而不是要求我们构建它,情况会好得多。

您似乎已经制定了一种解析替换映射的自定义方法。我建议使用一个像样的解析器,例如Config::INI::Reader

#!/usr/bin/env perl

use strict;
use warnings;

use Config::INI::Reader;

my $ini_contents = <<'EO_INI';
\nleftarrow = {\not\leftarrow}
\nrightarrow = {\not\rightarrow}
\nleftrightarrow = {\not\leftrightarrow}
EO_INI

my $tex_source = <<'EO_TEX';
Lorem ipsum dolor \not\leftarrow{} sit amet, ea quem idque senserit eum, in
\not \rightarrow{} duo amet recusabo sensibus. Mei velit suavitate ei, ferri
consequuntur vis eu, qui unum volumus an. Rebum democritum no nec, et \not
\leftrightarrow{} eam natum patrioque, mentitum evertitur reprimique nec te.
Usu et docendi \not\rightarrow{} partiendo, eos ut assum errem simul.
EO_TEX

# Helper function to deal with matches with spaces
# because our mapping does not have sequences
# containing spaces.
sub match_to_key {
    my ($s) = @_;
    $s =~ s/\s+//g;
    return $s;
}

# Assume mappings appear in a single global section only
my $macro_definition = Config::INI::Reader->read_string($ini_contents)->{_};

# Assuming { and } need to be removed
for (values %$macro_definition) {
    s/^\{//;
    s/\}\z//;
}

# map command sequences to replacement macros
$macro_definition = { reverse %$macro_definition };

my $command_sequence_pat = join '|',
    sort { length($b) <=> length($a) }
    map join('\s?', map quotemeta, m{ (\\\w+) }gx),
    keys %$macro_definition
;

print "Text before replacement:\n";

print ">>>$tex_source<<<\n\n";

$tex_source =~ s/($command_sequence_pat)/$macro_definition->{match_to_key($1)}/g;

print "Text after replacement:\n";

print ">>>$tex_source<<<\n\n";

请注意,原始文本的包装可能会搞砸。

输出:

Text before replacement:
>>>Lorem ipsum dolor \not\leftarrow{} sit amet, ea quem idque senserit eum, in
\not \rightarrow{} duo amet recusabo sensibus. Mei velit suavitate ei, ferri
consequuntur vis eu, qui unum volumus an. Rebum democritum no nec, et \not
\leftrightarrow{} eam natum patrioque, mentitum evertitur reprimique nec te.
Usu et docendi \not\rightarrow{} partiendo, eos ut assum errem simul.
<<<

Text after replacement:
>>>Lorem ipsum dolor \nleftarrow{} sit amet, ea quem idque senserit eum, in
\nrightarrow{} duo amet recusabo sensibus. Mei velit suavitate ei, ferri
consequuntur vis eu, qui unum volumus an. Rebum democritum no nec, et \nleftrightarrow{} eam natum patrioque, mentitum evertitur reprimique nec te.
Usu et docendi \nrightarrow{} partiendo, eos ut assum errem simul.
<<<