在新行中匹配图案后,逐行合并两个文件



如果不匹配,我需要合并两个文件。非静态中的匹配是随机的,但总是在一个特定标签之后

文件1

<can update="x" site="merge-xml-01" site_id="foo.com" xmltv_id="foo@com">foo@com</can>
<can update="x" site="merge-xml-02" site_id="bar.com" xmltv_id="bar@com">bar@com</can>
<can update="x" site="merge-xml-03" site_id="xxx.com" xmltv_id="xxx@com">xxx@com</can>

文件2

<can offset="u" same_as="foo.com" id="foo 01">foo 01</can>
<can offset="u" same_as="foo.com" id="foo 02">foo 02</can>
<can offset="u" same_as="bar.com" id="bar 01">bar 01</can>
<can offset="u" same_as="xxx.com" id="xxx 01">xxx 01</can>
<can offset="u" same_as="xxx.com" id="xxx 02">xxx 02</can>
<can offset="u" same_as="xxx.com" id="xxx 03">xxx 03</can>

我需要把文件号3做成这个

<can update="x" site="merge-xml-01" site_id="foo.com" xmltv_id="foo@com">foo@com</can>
<can offset="u" same_as="foo.com" id="foo 01">foo 01</can>
<can offset="u" same_as="foo.com" id="foo 02">foo 02</can>
<can update="x" site="merge-xml-02" site_id="bar.com" xmltv_id="bar@com">bar@com</can>
<can offset="u" same_as="bar.com" id="bar 01">bar 01</can>
<can update="x" site="merge-xml-03" site_id="xxx.com" xmltv_id="xxx@com">xxx@com</can>
<can offset="u" same_as="xxx.com" id="xxx 01">xxx 01</can>
<can offset="u" same_as="xxx.com" id="xxx 02">xxx 02</can>
<can offset="u" same_as="xxx.com" id="xxx 03">xxx 03</can>

我希望很清楚,如果文件1中的标签"site_id="与文件2中的标签"same_as="匹配,我需要合并数据。

老实说,我不知道我能做些什么来得到这个结果,我检查了很多帖子,但所有的合并数据都在同一行,我在新行上找不到合并数据的东西。

我喜欢是否可以使用sed或awk,但欢迎任何建议。

谢谢你的建议。

假设文件2按密钥排序

$ awk -F' |=' 'NR==FNR {for(i=1;i<NF;i++) if($i=="site_id") {a[$(i+1)]=$0; break}; next} 
{k=""; for(i=1;i<NF;i++) if($i=="same_as") {k=$(i+1); break}
if(!p[k]++) print a[k]}1' file1 file2
<can update="x" site="merge-xml-01" site_id="foo.com" xmltv_id="foo@com">foo@com</can>
<can offset="u" same_as="foo.com" id="foo 01">foo 01</can>
<can offset="u" same_as="foo.com" id="foo 02">foo 02</can>
<can update="x" site="merge-xml-02" site_id="bar.com" xmltv_id="bar@com">bar@com</can>
<can offset="u" same_as="bar.com" id="bar 01">bar 01</can>
<can update="x" site="merge-xml-03" site_id="xxx.com" xmltv_id="xxx@com">xxx@com</can>
<can offset="u" same_as="xxx.com" id="xxx 01">xxx 01</can>
<can offset="u" same_as="xxx.com" id="xxx 02">xxx 02</can>
<can offset="u" same_as="xxx.com" id="xxx 03">xxx 03</can>

ps。这应该比其他用于大文件的解决方案快得多。

IF您可以肯定这些格式是一致的,并且总是在一行上。。。

$: cat c $ file 1 is a, file 2 is b
#! /bin/env bash
while read -r line
do pat="${line##* site_id="}"
pat="${pat%%"*}"
echo "$line"
grep " same_as=["]$pat["] " b
done < a
$: c
<can update="x" site="merge-xml-01" site_id="foo.com" xmltv_id="foo@com">foo@com</can>
<can offset="u" same_as="foo.com" id="foo 01">foo 01</can>
<can offset="u" same_as="foo.com" id="foo 02">foo 02</can>
<can update="x" site="merge-xml-02" site_id="bar.com" xmltv_id="bar@com">bar@com</can>
<can offset="u" same_as="bar.com" id="bar 01">bar 01</can>
<can update="x" site="merge-xml-03" site_id="xxx.com" xmltv_id="xxx@com">xxx@com</can>
<can offset="u" same_as="xxx.com" id="xxx 01">xxx 01</can>
<can offset="u" same_as="xxx.com" id="xxx 02">xxx 02</can>
<can offset="u" same_as="xxx.com" id="xxx 03">xxx 03</can>

逐行读取文件,找到URL并在第二个文件中搜索。

while read -r line; do
echo "$line" >> file3
url=$(sed 's/.*site_id="([^"]+)".*/1/' <<< $line)
grep $url file2 >> file3
done < file1
$ cat file3
<can update="x" site="merge-xml-01" site_id="foo.com" xmltv_id="foo@com">foo@com</can>
<can offset="u" same_as="foo.com" id="foo 01">foo 01</can>
<can offset="u" same_as="foo.com" id="foo 02">foo 02</can>
<can update="x" site="merge-xml-02" site_id="bar.com" xmltv_id="bar@com">bar@com</can>
<can offset="u" same_as="bar.com" id="bar 01">bar 01</can>
<can update="x" site="merge-xml-03" site_id="xxx.com" xmltv_id="xxx@com">xxx@com</can>
<can offset="u" same_as="xxx.com" id="xxx 01">xxx 01</can>
<can offset="u" same_as="xxx.com" id="xxx 02">xxx 02</can>
<can offset="u" same_as="xxx.com" id="xxx 03">xxx 03</can>

这可能对你有用(GNU sed(:

sed 's#.*same_as=("[^"]*").*#/site_id=1/a&#' file2 | sed -f - file1

将file2转换为sed脚本,该脚本在将same_as的值与file1的site_id相匹配时追加每一行。然后通过管道将生成的脚本传递到针对file1运行的sed的第二次调用。每次读入file1中的一行时,都会按顺序将file2中的行附加到该行

要从文件1中删除在文件2中不匹配的行,请使用:

sed -e 's#.*same_as=("[^"]*").*#/site_id=1/{a&nx;s/^/x/;x}#' file2 |
sed -f - -e 'x;/x/{z;x;b};d' file1

这在保留空间中添加了一个标志,当添加了来自文件2的行时和当没有设置时设置该标志,以从文件1 中删除当前记录

最新更新