在unix中检查一个文件中的字符串是否存在于另一个文件中

在unix中检查一个文件中的字符串是否存在于另一个文件中,unix,awk,sed,grep,Unix,Awk,Sed,Grep,我有一个包含版本名和版本号的文件。第一个文件的内容如下所示: File1- <Line contains the name of product1> package_name0_9_8 >= 1.2.3x-4.5.6 package_name0_9_8-32bit >= 3.6.1g-3.5.1 package_name0_9_8-xx >= 6.3.2v-3.0.4 <Line contains the name of product2> anoth

我有一个包含版本名和版本号的文件。第一个文件的内容如下所示:

File1-

<Line contains the name of product1>
package_name0_9_8 >= 1.2.3x-4.5.6
package_name0_9_8-32bit >= 3.6.1g-3.5.1
package_name0_9_8-xx >= 6.3.2v-3.0.4
<Line contains the name of product2>
anotherpackage_name0_9_8 >= 3.5.6u-3.6.5
File1-
包名称0\u 9\u 8>=1.2.3x-4.5.6
软件包名称0\u 9\u 8-32位>=3.6.1g-3.5.1
包名称0\u 9\u 8-xx>=6.3.2v-3.0.4
另一个包名称0\u 9\u 8>=3.5.6u-3.6.5
以及

File2.xml-
.
.
是否有方法检查File1中是否存在文件包名称为File2的文件包名称,以及File1中文件包名称的对应版本是否与File2中文件包名称的对应版本一致

坦率地说,我在连接“grep”和“awk”命令以及此处要使用的选项方面非常弱。请帮忙。

sed-n's²。*s#;s/*>=*/\\)“*version=“/p”File1>/tmp/File1.sed
sed -n 's².*²s#<package name="\\(&"/>#\\1 Present#p²;s/ *>= */\\)" *version="/p' File1 > /tmp/File1.sed
sed -n -f /tmp/File1.sed File2
rm /tmp/File1.sed 
sed-n-f/tmp/File1.sed File2 rm/tmp/File1.sed
  • 不像awk那样在指令上工作,而是在GNU上工作(posix版本so
    --posix
  • 您可以更改
    \\1显示的输出消息
    文本,其中
    \\1
    将作为程序包名称(只需少量修改,也可以使用版本)

看起来您已经得到了一个更简短的解决方案,其格式更接近您所需的格式。但是,既然我问Python解决方案是否可行,而您说可以,请查看此处的代码:

(我只调试了一点,但它似乎至少比您的示例文件多一点。我将代码发布到了公共领域。根据CC制造商的说法,CC-BY-SA不是软件许可证;因此,这就是为什么我没有在这里发布它,因为在这里发布它将授予它该许可证。此外,您还可以通过通过提供的链接将c转换为Python。)

基本上,这是一个非常复杂的文本解析。没有太多的算法来解释。它获取两个文件的内容,去掉包,它们的版本和操作数(将所有这些放在字典中以备以后使用),并在其他文件的行中循环并比较版本;然后它会告诉您哪些匹配,哪些不匹配。

对于a in$(sed-n'/>=/p'File1.txt | grep-o'^[^]*');对于b in$(sed-n/^$a/{s/*>=\(.\$/\1/p}”File1.txt);do((!$(grep-c“$a.*$b”File2.txt))&(echo“$a$b>>缺少);完成;完成;

这是一个快速的一行-你可以打印出来有点漂亮

其工作方式是嵌套for循环,该循环将两个部分分别捕获为变量(您可以通过read执行此操作,如果需要,将它们放在一个循环中),然后使用grep对第二个文件中的发生次数进行计数,并且每当计数为零时,它将反转进行测试的值(())将“真”设置为“真”,并将丢失的包回显到文件missing_pkgs.txt中

这里是另一个快速的一行程序,除了通过read加载一个循环和变量更有效之外,它也做同样的事情


每次读取时
;读取一个b<>缺失的\u pkgs.txt);完成<>缺失的\u pkgs.txt);done<你对Python解决方案感兴趣吗?是的,非常欢迎。Python解决方案就可以了。@Sheller:谢谢。是的,那句话没有意义。我想,我会这样输出。或者你可以将第一个命令的输出发送到第二个:
sed-n'stuff'File1 | sed-n-f-File2
@NeronLeVelu:我可以知道第一行中的方形符号是什么吗?我不熟悉那个符号。另外,您能详细说明第二个要点吗?
#
一样在这里被用作传统
s///
的模式分隔符,而不是在模式本身中使用的
/
。sed将
s
之后的第一个字符作为分隔符。因为它用于2个不同的sed(第一个创建第二个),所以我在bash(linux)中使用了2个不同的分隔符。@aragaer,但我在这里使用AIX KSH,所以
|-在这种情况下意外失败。不管怎样,这是一个很好的观点。对不起,再说一遍!我对此还不是很清楚。这个符号可以被替换吗?另外,请对
\\1礼物发表评论
谢谢!根据您的想法,我尝试了
sed-n/>=/p“File1 | grep-o”^[^]*>包名
sed-n/^/{s/*>=\(.\)/\\1/p}”文件1>包版本
。我刚刚将这些行放入一个shell脚本(只是为了使它更简单和跨协议)并运行该脚本。现在,相同的shell脚本应该检查
File2
package\u名称的
line1
,然后使用
File2
检查
package\u版本的
line1
。请帮忙。我对shell脚本也没有太多的想法。我会选择第二个版本,因为它更简单,如果需要的话,你可以进一步将它简化为:while read a b;do(!$(grep-c“$a.*$b”File2.txt))&(echo“$a$b”>>缺少_pkgs.txt);我现在明白了。另外,在读取a b时,如何将
$1
$3
存储到上一部分
中使用的两个独立变量中;这样做-如果您在完成流程替换的输出后查看脚本的结尾,如果您想更改当前的输出格式,您可以修改部分:echo“$a$b”>>以满足您的需要。
sed -n 's².*²s#<package name="\\(&"/>#\\1 Present#p²;s/ *>= */\\)" *version="/p' File1 > /tmp/File1.sed
sed -n -f /tmp/File1.sed File2
rm /tmp/File1.sed