Bash - 如何使用另一个文件中存在的模式获取文件内容的行号?

时间:2017-02-23 07:21:13

标签: bash grep

我有一个基本文件和模式文件,如下所示:

基础文件:

#!/usr/bin/env php
<?php
include 'first.php';
$z=0;
function sayHello() {
   return "hellobye";
}
echo "<br /></br />";
?>

模式文件:

#!/usr/bin/env php
<?php 
include 'first.php';
$z = 0;
echo "<br /></br />";
?>

所以我想使用bash从模式文件中存在的基本文件中提取其数字。其中一些模式未使用,我想删除它们。例如<?php?>

输出应该是这样的:

1:#!/usr/bin/env php
3:include 'first.php';
4:$z = 0;
8:echo "<br /></br />";

另一个例子是:

基础文件:

#!/usr/bin/env
<?php 
include 'second.php';
function saybye()
{
    return "bye";
}
echo "<br />";
function sayHello()
{
    return "hellobye";
}
?>

模式文件:

#!/usr/bin/env
<?php 
include 'second.php';
function saybye()
{
    return "bye";
}
echo "<br />";
?>

输出应该是这样的:

1:#!/usr/bin/env
3:include 'second.php';
4:function saybye()
5:{
6:    return "bye";
7:}
8:echo "<br />";

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

尝试一个简单的grep -nf

$grep -nf pattern base
1:#!/usr/bin/env php
3:include 'first.php';
4:$z = 0;
8:echo "<br /></br />";
9:?>

如果您要删除以&#34;?&gt;&#34;

开头的行
$grep -nf pattern base | grep -v "?>"
1:#!/usr/bin/env php
3:include 'first.php';
4:$z = 0;
8:echo "<br /></br />";

输入是 -

$cat pattern

#!/usr/bin/env php
<?php 
include 'first.php';
$z = 0;
echo "<br /></br />";
?>

$cat base
#!/usr/bin/env php
<?php
include 'first.php';
$z = 0;
function sayHello() {
   return "hellobye";
}
echo "<br /></br />";
?>

答案 1 :(得分:0)

可以使用grep和两个sed调用来实现它:

$ grep -nFwf file1 test2 | sed s/\?// | sed /[0-9].*\:\>/d 
1:#!/usr/bin/env php
3:include 'first.php';
4:$z=0;
8:echo "<br /></br />";

file1:

#!/usr/bin/env php
<?php 
include 'first.php';
$z=0;
echo "<br /></br />";
?>

file2的:

#!/usr/bin/env php
<?php
include 'first.php';
$z=0;
function sayHello() {
   return "hellobye";
}
echo "<br /></br />";
?>

grep调用将生成匹配行的输出,最后两个sed调用将删除?><?php模式。

答案 2 :(得分:0)

这将在2个文件之间进行全行字符串匹配:

$ awk '
    BEGIN{ bad["<?php"]; bad["?>"]; OFS=";" }
    NR==FNR{ if ( !($0 in bad) ) good[$0]; next }
    $0 in good{ print FNR, $0 }
' pattern base
1;#!/usr/bin/env php
3;include 'first.php';
8;echo "<br /></br />";

请注意,$z行不匹配,因为=文件中的base周围没有空格,=中的空格不在pattern 1}}文件:

$ grep '$z' pattern base
pattern:$z = 0;
base:$z=0;

如果您希望完全忽略所有空格,您可以这样做:

$ awk '
    BEGIN{ bad["<?php"]; bad["?>"]; OFS=";" }
    { nospace=$0; gsub(/[[:space:]]+/,"",nospace) }
    NR==FNR{ if ( !(nospace in bad) ) good[nospace]; next }
    nospace in good{ print FNR, $0 }
' pattern base
1;#!/usr/bin/env php
3;include 'first.php';
4;$z=0;
8;echo "<br /></br />";

但是你必须要小心,连接会产生错误的匹配。如果您希望所有空间得到平等对待,您可以这样做:

$ awk '
    BEGIN{ bad["<?php"]; bad["?>"]; OFS=";" }
    { anyspace=$0; gsub(/[[:space:]]+/,RS,anyspace) }
    NR==FNR{ if ( !(anyspace in bad) ) good[anyspace]; next }
    anyspace in good{ print FNR, $0 }
' pattern base
1;#!/usr/bin/env php
3;include 'first.php';
8;echo "<br /></br />";

但请注意,由于其中一个文件中的$z周围没有空格,因此sill找不到=行。如果您想要将每个标点字符视为被空格包围,同时仍然进行字符串比较,则可以执行以下操作:

$ awk '
    BEGIN{ bad[RS"<"RS"?"RS"php"]; bad[RS"?"RS">"RS]; OFS=";" }
    { anyspace=$0; gsub(/[[:punct:]]/," & ",anyspace); gsub(/[[:space:]]+/,RS,anyspace) }
    NR==FNR{ if ( !(anyspace in bad) ) good[anyspace]; next }
    anyspace in good{ print FNR, $0 }
' pattern base
1;#!/usr/bin/env php
3;include 'first.php';
4;$z=0;
8;echo "<br /></br />";

一旦你澄清了你的要求,我们就可以帮助你编写一个脚本来做你真正想做的事情,无论是字符串还是正则表达式比较,是否需要部分匹配或完全匹配,以及是否应该使用空格按字面意思对待或忽略。