Linux 显示行中不常见的部分

Linux 显示行中不常见的部分,linux,bash,Linux,Bash,嗨,我有两个包含路径的文件。我想比较这两个文件,只显示行中不常见的部分 1.txt: /home/folder_name/abc 2.txt: /home/folder_name/abc/pqr/xyz/mnp 我想要的输出: /pqr/xyz/mnp 我怎样才能做到这一点呢?这一点awk可以做到: $ awk 'NR==FNR {a[++i]=$0; next} { b[++j]=$0; if(length(a[j])>length(b[j])) {t=a[j];

嗨,我有两个包含路径的文件。我想比较这两个文件,只显示行中不常见的部分

1.txt:

/home/folder_name/abc
2.txt:

/home/folder_name/abc/pqr/xyz/mnp
我想要的输出:

/pqr/xyz/mnp

我怎样才能做到这一点呢?

这一点awk可以做到:

$ awk 'NR==FNR {a[++i]=$0; next}
{
    b[++j]=$0; 
    if(length(a[j])>length(b[j])) {t=a[j]; a[j]=b[j]; b[j]=t}
    sub(a[j],"",b[j]);
    print b[j]
}' 2.txt 1.txt  # or 2.txt 1.txt, it doesn't matter
  • 将第一个文件中的行写入数组
    a
  • 将第二行写到
    b
  • 如果
    a[j]
    b[j]
    长,则交换
    a[j]
    b[j]
    (如果较长的文本始终在
    b
    中,则可能不必这样做)
  • b[j]
    中移除
    a[j]
    中找到的零件,然后打印
    b[j]
这是一个普遍的解决办法;它不假设匹配项位于行的开头,或者一个文件行的内容应该从另一个文件行中删除。如果您能够承担这些假设,那么脚本可以简化


如果匹配可能在行中出现多次,则可以使用
gsub
而不是
sub
执行全局替换。

此脚本将比较文件中的所有行,并仅输出行中的更改。
首先,它统计第一个文件中的行数

然后我开始一个循环,循环的行数。
声明两个文件中同一行的两个变量。
比较这些行,如果它们是相同的输出。
如果没有,则将字符串的重复部分替换为零(有效地删除它们)
我使用
作为
sed
中的分隔符,因为变量包含
/
。因此,如果它们包含<代码>:,那么您可能需要考虑更改它们。

可能不是最有效的解决方案,但它确实有效

#!/bin/bash

NUMOFLINES=$(wc -l < "1.txt")
echo $NUMOFLINES

for ((i = 1 ; i <= $NUMOFLINES ; i++)); do

f1=$(sed -n $i'p' 1.txt)
f2=$(sed -n $i'p' 2.txt)

if [[ $f1 < $f2 ]]; then
        echo -n "Line $i:"
        sed 's:'"$f1"'::' <<< "$f2"
elif  [[ $f1 > $f2 ]]; then
        echo -n "Line $i:"
        sed 's:'"$f2"'::' <<< "$f1"
else
        echo "Line $i: Both lines are the same"
fi

echo ""

done
#/bin/bash
NUMOFLINES=$(wc-l<“1.txt”)
echo$NUMOFLINES

对于((i=1;i考虑到您在
1.txt
2.txt
中有字符串,下面的代码就可以了

paste 1.txt 2.txt | 
while read a b; 
do 
    if [[ ${#a} -gt ${#b} ]];
    then
        echo ${a/$b}; 
    else
        echo ${b/$a};
    fi;
done;
这就是它在我的系统上的工作原理

shiplu@:~/test/bash$ cat 1.txt 
/home/shiplu/test/bash
/home/shiplu/test/bash/hello/world
shiplu@:~/test/bash$ cat 2.txt 
/home/shiplu/test/bash/good/world
/home/shiplu/test/bash
shiplu@:~/test/bash$ paste 1.txt 2.txt | 
> while read a b; 
> do 
>     if [[ ${#a} -gt ${#b} ]];
>     then
>         echo ${a/$b}; 
>     else
>         echo ${b/$a};
>     fi;
> done;
/good/world
/hello/world

如果您碰巧使用了bash,可以尝试以下方法:

echo $(diff <(grep -o . 1.txt) <(grep -o . 2.txt) \
| sed -n '/^[<>]/ {s/^..//;p}' | tr -d '\n')

这通过添加行结束标记(例如%)扩展了单行解决方案,diff通过在左侧添加%和在右侧添加%%强制将其包含在其输出中。

如果两个文件中的每一行始终只有一行,则以下操作有效:

perl -lne '$a=$_ if($.==1);print $1 if(/$a(.*)/ && $.==2)' 1.txt 2.txt
测试如下:

> cat 1.txt
/home/folder_name/abc
> cat 2.txt
/home/folder_name/abc/pqr/xyz/mnp
> perl -lne '$a=$_ if($.==1);print $1 if(/$a(.*)/ && $.==2)' 1.txt 2.txt
/pqr/xyz/mnp
> 

为什么不使用diff?你只需要不同的部分吗?一个总是另一个的前缀吗?1总是2的前缀吗?或者可以反过来吗?即使两个文件中的行相同,这仍然打印行吗?而且在一个有多行的文件中它似乎对我不起作用?@Jidder在回答你的第一个问题时,我不是这是一个要求。我已经对第二个问题进行了编辑。谢谢。第一个问题是,如果行相同,它仍在打印,用户会觉得这是它们之间的区别,不管怎样,您的编辑解决了这两个问题。做得好!不是bash!是perl!我用过,也不是,您用的是读取一个具有变量空间的B</代码>。由于使用粘贴,它会考虑第二个字,从<代码> a <代码>为<代码> b>代码>,b还包含应该在<代码> b <代码>中的数据。
> cat 1.txt
/home/folder_name/abc
> cat 2.txt
/home/folder_name/abc/pqr/xyz/mnp
> perl -lne '$a=$_ if($.==1);print $1 if(/$a(.*)/ && $.==2)' 1.txt 2.txt
/pqr/xyz/mnp
>