Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何在unix中比较和替换不同行中的字符串_Regex_Unix_Awk_Sed - Fatal编程技术网

Regex 如何在unix中比较和替换不同行中的字符串

Regex 如何在unix中比较和替换不同行中的字符串,regex,unix,awk,sed,Regex,Unix,Awk,Sed,我想比较和替换unix中不同行中的字符串 例如,我有一个文件,每行有两个单词 <a> <b> <d> <e> <b> <c> <c> <e> 如果任何行的第二个字与任何其他行的第一个字匹配,则该行的第二个字应替换为匹配行的第二个字,并应迭代,直到该行的第二个字与另一行的第一个字不匹配为止 我需要这样的结果 <a> <e> <b> <e> <c

我想比较和替换unix中不同行中的字符串

例如,我有一个文件,每行有两个单词

<a> <b>
<d> <e>
<b> <c>
<c> <e>

如果任何行的第二个字与任何其他行的第一个字匹配,则该行的第二个字应替换为匹配行的第二个字,并应迭代,直到该行的第二个字与另一行的第一个字不匹配为止

我需要这样的结果

<a> <e>
<b> <e>
<c> <e>
<d> <e>

我是unix新手,不知道如何实现它。有谁能给我们一些建议或解释一下我们是如何做到这一点的吗

#!/usr/bin/perl
use warnings;
use strict;

my (@buff);
sub output {
    my $last = pop @buff;
    print map "$_ $last\n", @buff;
    @buff = ();
}

while (<>) {
    my @F = split;
    output() if @buff and $F[0] ne $buff[-1]; # End of a group.
    push @buff, $F[0] unless @buff;           # Start a new group.
    push @buff, $F[1];
}

output();                                     # Don't forget to print the last buffer.
#/usr/bin/perl
使用警告;
严格使用;
我的(@buff);
子输出{
我的$last=pop@buff;
打印地图“$\u$last\n”,@buff;
@buff=();
}
而(){
我的@F=分裂;
如果@buff和$F[0]ne$buff[-1];#组结束,则输出()。
按@buff,$F[0],除非@buff;#启动一个新组。
推送@buff,$F[1];
}
输出();#别忘了打印最后一个缓冲区。
说明:逐行阅读输入。保留一个要用相同的第二个单词打印的单词列表。如果第一个字与前一行的第二个字不同,则打印缓冲输出。

Perl:

#!/usr/bin/perl
use warnings;
use strict;

my (@buff);
sub output {
    my $last = pop @buff;
    print map "$_ $last\n", @buff;
    @buff = ();
}

while (<>) {
    my @F = split;
    output() if @buff and $F[0] ne $buff[-1]; # End of a group.
    push @buff, $F[0] unless @buff;           # Start a new group.
    push @buff, $F[1];
}

output();                                     # Don't forget to print the last buffer.
awk '{i++;a[i]=$1;b[i]=$2;next}
      END{
            for(i=1;i in a;i++)
            {
              f=1;
              while (f==1)
              {
                f=0;
                for(j=i+1;j in a;j++)
                {
                  if(b[i]==a[j])
                  {
                    b[i]=b[j];
                    f=1;
                  }
                }
              }
            }
            for(i=1;i in a;i++)
            {
              print a[i],b[i];
            }
          }' input.txt
#/usr/bin/perl
使用警告;
严格使用;
我的(@buff);
子输出{
我的$last=pop@buff;
打印地图“$\u$last\n”,@buff;
@buff=();
}
而(){
我的@F=分裂;
如果@buff和$F[0]ne$buff[-1];#组结束,则输出()。
按@buff,$F[0],除非@buff;#启动一个新组。
推送@buff,$F[1];
}
输出();#别忘了打印最后一个缓冲区。
说明:逐行阅读输入。保留一个要用相同的第二个单词打印的单词列表。如果第一个字与前一行的第二个字不同,则打印缓冲输出

awk '{i++;a[i]=$1;b[i]=$2;next}
      END{
            for(i=1;i in a;i++)
            {
              f=1;
              while (f==1)
              {
                f=0;
                for(j=i+1;j in a;j++)
                {
                  if(b[i]==a[j])
                  {
                    b[i]=b[j];
                    f=1;
                  }
                }
              }
            }
            for(i=1;i in a;i++)
            {
              print a[i],b[i];
            }
          }' input.txt
输入:

<a> <b>
<d> <e>
<b> <c>
<c> <e>
<a> <b>
<e> <z>
<b> <e>
致:

这是:

for(j=i+1;j in a;j++)
致:

还请注意,此代码假定不存在行的第二个字同时等于行的第一个字和第二个字的情况,即:

<a> <b>
<e> <z>
<b> <b>

在这种情况下,代码的执行将永远不会结束

输入:

<a> <b>
<d> <e>
<b> <c>
<c> <e>
<a> <b>
<e> <z>
<b> <e>
致:

这是:

for(j=i+1;j in a;j++)
致:

还请注意,此代码假定不存在行的第二个字同时等于行的第一个字和第二个字的情况,即:

<a> <b>
<e> <z>
<b> <b>


在这种情况下,代码的执行将永远不会结束。

这显然是递归下降解决方案的一种情况:

$ cat tst.awk
function descend(node) {return (map[node] in map ? descend(map[node]) : map[node])}
{ map[$1] = $2 }
END { for (key in map) print key, descend(key) }

$ awk -f tst.awk file
<a> <e>
<b> <e>
<c> <e>
<d> <e>

$cat文件
$awk-f tst.awk文件
*
*
*
*
如果需要输出顺序与输入顺序匹配和/或打印两次重复行,请将脚本底部的两行更改为:

{ keys[++numKeys] = $1; map[$1] = $2 }
END {
    for (keyNr=1; keyNr<=numKeys; keyNr++) {
        key = keys[keyNr]
        print key, descend(key)
    }
}
{keys[++numKeys]=1;map[$1]=2}
结束{

对于(keyNr=1;keyNr这显然是递归下降解决方案的一种情况:

$ cat tst.awk
function descend(node) {return (map[node] in map ? descend(map[node]) : map[node])}
{ map[$1] = $2 }
END { for (key in map) print key, descend(key) }

$ awk -f tst.awk file
<a> <e>
<b> <e>
<c> <e>
<d> <e>

$cat文件
$awk-f tst.awk文件
*
*
*
*
如果需要输出顺序与输入顺序匹配和/或打印两次重复行,请将脚本底部的两行更改为:

{ keys[++numKeys] = $1; map[$1] = $2 }
END {
    for (keyNr=1; keyNr<=numKeys; keyNr++) {
        key = keys[keyNr]
        print key, descend(key)
    }
}
{keys[++numKeys]=1;map[$1]=2}
结束{

对于(keyNr=1;keyNrby)“它应该迭代,直到没有匹配…”你的意思是它应该比较第1行和第3行,然后再比较第4行等等?是的。你是对的,阿什坎!它应该在所有行中搜索匹配项。以此作为输入
第一行,
第二行和
第三行你想要的输出是什么?期望的输出现在将是第一行和第一行的第二个字第二行的t字是相等的,它不应该被替换为?即变成或有其他一些条件?用“并且它应该迭代直到没有匹配…”你的意思是它应该比较第1行和第3行,然后再比较第4行等等?是的。你是对的,阿什坎!它应该在所有行中搜索匹配项。以此作为输入
第一行,
第二行和
第三行你想要的输出是什么?期望的输出现在将是第一行和第一行的第二个字第二行的t字是相等的,是不是应该替换为?即变成或有其他一些条件?嗨,乔洛巴..谢谢你的代码和解释!!它是否只与前一行比较(第一个字与前一行的第二个字不同).如果它能比较所有的线就好了。我怎么能做到呢?我不知道perl@shalini:试试。将其保存到文件
compare.pl
,运行
perl compare.pl input
,然后查看。嗨,乔洛巴,谢谢你的建议。我尝试了你的代码。它不起作用。它给出了相同的输出!@shalini:你希望得到什么输出?@shalini根据您的描述,是否应该给出相同的输出。
如果第1行的第二个单词与第2行的第一个单词匹配,则第1行的第二个单词应替换为第2行的第二个单词,并应迭代,直到第1行的第二个单词与第2行的第一个单词不匹配。请更新您的问题来展示你真正需要的东西。嗨,Choroba..谢谢你的代码和解释!!它是否只与前一行进行比较(前一行的第一个单词与前一行的第二个单词不同).如果它能比较所有的线就好了。我怎么能做到呢?我不知道perl@shalini:试试。将其保存到文件
compare.pl
,运行
perl compare.pl input
,然后查看。嗨,乔洛巴,谢谢你的建议。我尝试了你的代码。它不起作用。它给出了相同的输出!@shalini:你希望得到什么输出?@shalini根据您的描述,是否应该给出相同的输出。
如果第1行的第二个字与第2行的第一个字匹配,则第1行的第二个字应替换为第二个字