linux - 匹配两个文件中的字符串,并将第一个文件中匹配字符串的行追加到第二个文件的行尾

标签 linux bash awk grep

所以这有点棘手,我费了好大劲才弄明白。

我有两个不同的文件,一个是这样的 rackdiag 格式:

#file1
rackdiag {
  rack {
    42U;
    description = "1.1.1";
    1: "serverone" [4U];
    5: servertwo [2U];
    7: serverthree\nblah [3U];
  }
  rack {
    42U;
    description = "1.1.2";
    1: servertwoone [4U];
    5: "servertwotwo" [2U];
   }
 }

等等

另一个是服务器名称列表,如下所示:

#file2
serverone.domain.com
servertwo.domain.com
serverthree.domain.com

我正在尝试匹配两个文件之间的字符串,并将具有匹配字符串的行从第一个文件插入到第二个文件的末尾,并添加一些内容。我希望它在第二个文件中像这样结束:

serverone.domain.com #1.1.1 1: "serverone" [4U];
servertwo.domain.com #1.1.1 5: servertwo [2U];
servertwoone.domain.com #1.1.2 1: servertwoone [4U]; 

我设法做到了这一点:

#!/bin/bash

cat serverlist.txt | while read line;
do
#grep for matching strings and output entire line when match found to $line2 variable
line2=$(grep -w "$line" row01.txt)
echo "$line "#" $line2" 
done > halp.txt
exit

输出这个:

servertwo.domain.com #5: servertwo.domain.com [2U];

但我注意到由于某种原因它缺少一些应该匹配的内容。

比如,在实际文件中我有这一行

   33: servername [2U];

第二个文件中的这一行:

servername.blahhosting.com

当我尝试运行脚本时,输出仅为:

servername.blahhosting.com #

谁能帮我让 1.1.1/1.1.2 等出现在输出中,并弄清楚为什么它可能会丢失一些匹配的行?

非常感谢!

编辑 1:

rackdiag {
   rack {
       42U;
       description = "5.1.1";
       1: servertwoone [4U];
       1: "servertwoone" [4U];
       1: servertwoone\nserveronetwo [4U];
       1: "servertwoone\nserveronetwo" [4U];
       1: servertwo-1\nserverone1 [4U];
       1: "servertwo-2\nserverone2" [4U];
       1: servertwoone-1 [4U];
       1: servertwoone-2 [4U];
       1: servertwoone1 [4U];
       1: servertwoone2 [4U];
       1: servertwoone;
   }
   rack {
       42U;
       description = "5.1.2";
       1: server two one [4U];
       1: servertwoone [4U];
       1: server.two.one [4U];
   }
}

如果没有[2U]等,最后是空白的,就是[1U]

如果名称带有\n,则表示服务器在物理外壳上有多个标签。 我想就是这样

最佳答案

您的问题不清楚,但这是解决问题的正确方法和开始:

$ cat tst.awk
NR==FNR {
    if ( $1 == "description" ) {
        desc = $NF
        gsub(/^"|";$/,"",desc)
    }
    else if ( $1 ~ /^[0-9]+:/ ) {
        nmbr = $1
        sub(/^[[:space:]]*[^[:space:]]+[[:space:]]+/,"")

        if ( $NF ~ /\[.*\];$/ ) {
            blob = $NF
            sub(/[^[:space:]]+$/,"")
        }
        else {
            blob = "[1U];"
        }
        sub(/[[:space:]]+$/,"")

        numSrvrs = split($0,srvrs,/\\n/)
        for (srvrNr=1; srvrNr<=numSrvrs; srvrNr++) {
            srvr = srvrs[srvrNr]
            gsub(/^"|"$/,"",srvr)
            srvr2data[srvr] = "#" desc " " nmbr " " $0 " " blob
            printf "TRACE: srvr2data[%s] = <%s>\n", srvr, srvr2data[srvr]
        }
    }
    next
}
{
    srvr = $0
    sub(/\..*/,"",srvr)
    print $0, srvr2data[srvr]
}

针对您的前 2 个样本输入文件运行时:

$ awk -f tst.awk file1 file2
TRACE: srvr2data[serverone] = <#1.1.1 1: "serverone" [4U];>
TRACE: srvr2data[servertwo] = <#1.1.1 5: servertwo [2U];>
TRACE: srvr2data[serverthree] = <#1.1.1 7: serverthree\nblah [3U];>
TRACE: srvr2data[blah] = <#1.1.1 7: serverthree\nblah [3U];>
TRACE: srvr2data[servertwoone] = <#1.1.2 1: servertwoone [4U];>
TRACE: srvr2data[servertwotwo] = <#1.1.2 5: "servertwotwo" [2U];>
serverone.domain.com #1.1.1 1: "serverone" [4U];
servertwo.domain.com #1.1.1 5: servertwo [2U];
serverthree.domain.com #1.1.1 7: serverthree\nblah [3U];

当使用您的第三个输入文件(Edit 1 在您的问题中)并且没有关联的“file2”(因为您没有提供)运行时,您得到的只是作为数据的跟踪输出从第一个文件开始填充:

$ awk -f tst.awk file3 /dev/null
TRACE: srvr2data[servertwoone] = <#5.1.1 1: servertwoone [4U];>
TRACE: srvr2data[servertwoone] = <#5.1.1 1: "servertwoone" [4U];>
TRACE: srvr2data[servertwoone] = <#5.1.1 1: servertwoone\nserveronetwo [4U];>
TRACE: srvr2data[serveronetwo] = <#5.1.1 1: servertwoone\nserveronetwo [4U];>
TRACE: srvr2data[servertwoone] = <#5.1.1 1: "servertwoone\nserveronetwo" [4U];>
TRACE: srvr2data[serveronetwo] = <#5.1.1 1: "servertwoone\nserveronetwo" [4U];>
TRACE: srvr2data[servertwo-1] = <#5.1.1 1: servertwo-1\nserverone1 [4U];>
TRACE: srvr2data[serverone1] = <#5.1.1 1: servertwo-1\nserverone1 [4U];>
TRACE: srvr2data[servertwo-2] = <#5.1.1 1: "servertwo-2\nserverone2" [4U];>
TRACE: srvr2data[serverone2] = <#5.1.1 1: "servertwo-2\nserverone2" [4U];>
TRACE: srvr2data[servertwoone-1] = <#5.1.1 1: servertwoone-1 [4U];>
TRACE: srvr2data[servertwoone-2] = <#5.1.1 1: servertwoone-2 [4U];>
TRACE: srvr2data[servertwoone1] = <#5.1.1 1: servertwoone1 [4U];>
TRACE: srvr2data[servertwoone2] = <#5.1.1 1: servertwoone2 [4U];>
TRACE: srvr2data[servertwoone;] = <#5.1.1 1: servertwoone; [1U];>
TRACE: srvr2data[server two one] = <#5.1.2 1: server two one [4U];>
TRACE: srvr2data[servertwoone] = <#5.1.2 1: servertwoone [4U];>
TRACE: srvr2data[server.two.one] = <#5.1.2 1: server.two.one [4U];>

您没有告诉我们“[4U]”字段是什么,所以我将其命名为blob - 显然将其更改为任何名称。

关于linux - 匹配两个文件中的字符串,并将第一个文件中匹配字符串的行追加到第二个文件的行尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51557336/

相关文章:

mysql - 如何使用 bash 脚本链接 2 个 MySQL 数据库

bash - 子 shell 中的 shell split

linux - 如何在 shell 脚本中的正斜杠前插入反斜杠?

c - 使用非阻塞套接字获取 SIGPIPE——这正常吗?

linux - 字符串的正确转义策略

bash - 如何从 .sh shell 脚本中读取 -argument

bash - awk 在匹配后打印第一次出现

awk - 如何使用Lua基于列打印word?类似于 awk 的东西

linux - 远程 SSH 和命令集以及变量替换

linux - 如何停止、重启或查看启动应用程序的控制台日志?