使用perl查找文本文件中的行号和列号

时间:2017-05-30 13:43:53

标签: perl

我正在尝试在文件中的字符串完全匹配时获取linecolumn数字。然后,我可以获得line number而不是column number

需要在以下字符串中找到\amp

$str = '\begin{document}
    \title{Testing}
    It is important that the final model or models should make sense
    physically: at a minimum, this usually means that interactions should
    not be included without main effects nor higher-degree polynomial
    terms without their lower-degree relatives. Furthermore, if the model
    is to be used as a summary of the findings of one out of several
    studies bearing on the same phenomenon, main effects would usually be
    included whether significant or not.

    \begin{align}\label{equilibrium-disp-cyl}
    &G\left( {{\nabla ^{2}}{u_{r}} - \frac{2}{{{r^{2}}}}\frac{{\partial
{u_{\theta} }}}{{\partial \theta }} - \frac{{{u_{r}}}}{{{r^{2}}}}}
\right) \nonumber\\
\frac{1}{r}\frac{{\partial {u_{\theta} \amp}}}{{\partial \theta }} +
)\frac{1}{r}\frac{\partial }{{\partial \theta }}\left(
{\frac{{\partial {u_{r}}}}{{\partial r}} + \frac{{{u_{r}}}}{r} +
&G{\nabla ^{2}}{u_{z}} + ( {\lambda + G} )\frac{\partial }{{\partial
\end{align}
some para text continues....
    \begin{align}\label{equilibrium-disp-cyl}
&G\left( {{\nabla ^{2}}{u_{r}} - \frac{2}{{{r^{2}}}}\frac{{\partial
{u_{\theta} }}}{{\partial \theta }} - \frac{{{u_{r}}}}{{{r^{2}}}}}
\right) \nonumber\\
\frac{1}{r}\frac{{\partial {u_{\theta}}}}{{\partial \theta }} +
)\frac{1}{r}\frac{\partial }{{\partial \theta }}\left(
{\frac{{\partial {u_{r}}}}{{\partial r}} + \frac{{{u_{r}}}}{r} +
&G{\nabla ^{2}}{u_{z}} + ( {\lambda + G} \amp )\frac{\partial }{{\partial
\end{align}
some para text continues....
    \begin{align}\label{equilibrium-disp-cyl}
&G\left( {{\nabla ^{2}}{u_{r}} - \frac{2}{{{r^{2}}}}\frac{{\partial
{u_{\theta} }}}{{\partial \theta }} - \amp \frac{{{u_{r}}}}{{{r^{2}}}}}
\right) \nonumber\\
\frac{1}{r}\frac{{\partial {u_{\theta}}}}{{\partial \theta }} +
)\frac{1}{r}\frac{\partial }{{\partial \theta }}\left(
{\frac{{\partial {u_{r}}}}{{\partial r}} + \frac{{{u_{r}}}}{r} +
&G{\nabla ^{2}}{u_{z}} + ( {\lambda + G} \amp )\frac{\partial }{{\partial
\end{align}
';

我的代码:

my $_pres = ();
while($str=~m/\\begin\{align\}((?:(?!\\end\{align\}).)*)\\end\{align\}/sg)
{
    $_pres = $`; my $nolabel = $&;
    if($nolabel=~m/\\amp/i)
    {
        my $nwpre = $`; $newpre = $_pres.$nwpre;

        my ($line) = ($newpre =~s/\n/\n/g)+1;
        print "L: $line - Found amp...!!!\n";
    }
}

输出:

 L: 8 - Found amp...!!!
 L: 21 - Found amp...!!!
 L: 26 - Found amp...!!!

预期产出:

 L: 7:nn - \\amp command found ...!!!

有人可以指导我获取column号码,也会受到赞赏。

2 个答案:

答案 0 :(得分:2)

我认为\\begin\{align\}\\end\{align\}模式可以在更大的文本中找到这些段落(Latex的align环境)。

一旦你知道了,把剩下的部分分成几行,找到\amp的位置就很容易了

use warnings;
use strict;

# ADDED another "\amp", to the line before last
my $str = '\begin{align}\label{equilibrium-disp-cyl}  
    ... [ suppressed for brevity ]    
\right) = 0, \amp
\end{align}
';

while ($str =~ m/\\begin\{align\} (.*?) \\end\{align\}/sgx)
{
    my @lines = split /\n/, $1; 
    for my $i (0..$#lines)
    {
        my $line = $lines[$i];

        if ($line =~ /(\\amp)/i) 
        {
            print  "Found '$1' -- ";
            printf "Line number: %3d, match start: %2d, match end: %2d\n",
                $i+1, $-[0], $+[0];
        }
    }
}

这会使用@-@LAST_MATCH_START)和@+@LAST_MATCH_END)数组,这些数组会提供上次成功子匹配的开始和结束的偏移量。见Regex related variables in perlvar。由于只有一个匹配,我使用第一个元素$-[0]

我使用简单的(.*?)而不是中间不需要的负向前瞻。

恢复整个字符串(加上额外的\amp),上面打印

Found '\amp' -- Line number:   7, match start: 39, match end: 43
Found '\amp' -- Line number:  14, match start: 13, match end: 17

我在前一行添加了另一个\amp,以便进行更好的测试。

澄清:我们需要整个文件中的行号以及找到\amp的行中的行,在Latex的align环境中(由\begin{align}给出,{{1} }})。

\end{align}

use warnings; use strict; my $file = 'doc.tex'; open my $fh, '<', $file or die "Can't open $file: $!"; while (<$fh>) { if (/\\begin\{align\}/ .. /\\end\{align\}/) { if (/(\\amp)/i) { print "Found '$1' -- "; printf "Line number: %3d, match start: %2d, match end: %2d\n", $., $-[0], $+[0]; } } } 语句使用range operator来确保if匹配仅在/\\amp/环境中执行。 $. variable为我们提供了行号,align@-的使用与上述相同。

如果文件@+包含问题中显示的内容,则会打印

Found '\amp' -- Line number:  15, match start: 39, match end: 43
Found '\amp' -- Line number:  28, match start: 41, match end: 45
Found '\amp' -- Line number:  33, match start: 38, match end: 42
Found '\amp' -- Line number:  38, match start: 41, match end: 45

我可以确认该文本中的正确位置。

答案 1 :(得分:0)

添加索引检查;

my $index = index($str, '\\amp');
print "L: $line:$index - \\amp command found...!!!\n";

然而,它还不足以获得42,

[root@cal180 ~]# perl test.pl
L: 7:362 - \amp command found...!!!

听起来你可能也想解析括号?