【问题标题】:Merging two files based on a common column基于公共列合并两个文件
【发布时间】:2019-08-29 07:58:06
【问题描述】:

我有 2 个文件,一个是 telnet 命令的输出,另一个是 ip 和主机文件。我想根据公共 ip 合并这两个文件。

文件1:

25-08-2019_22.00.03 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ]
25-08-2019_22.00.03 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ] 

文件 2 是:

http://ip1:port1/cs/personal, CS
http://ip2:port2/cs/Satellite/out/, CS_SAT

并且想要一个如下的输出文件:

25-08-2019_22.00.03 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ] : CS
25-08-2019_22.00.03 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ] : CS_SAT

我不是 linux 专家,非常感谢任何帮助。

我尝试了 join -o file file2 之类的连接选项,但它没有提供所需的输出。

我尝试了 awk 命令,例如为第一个文件创建键值对并运行第二个文件,但它没有给出任何输出,是因为文件中的分隔符或特殊字符吗?

awk 'FNR==NR{a[$2]=$1;next}{if(a[$1]==""){a[$1]=0};
    print $1,$2,a[$1]}' file1 file2

【问题讨论】:

    标签: linux shell


    【解决方案1】:

    好吧,您必须以某种方式预处理输入文件。首先,使用带有sed 的一些正则表达式提取公共字段,然后是join。之后,您可以转换输出以匹配您的预期。

    代码中的注释:

    # recreate input
    cat <<EOF >file1
    25-08-2019_22.00.03 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ]
    25-08-2019_22.00.03 : Port port2 of URL http://ip2:port2/ is [ NOT OPEN ]
    EOF
    cat <<EOF >file2
    http://ip1:port1/cs/personal, CS
    http://ip2:port2/cs/Satellite/out/, CS_SAT
    EOF
    
    # join on the first field
    join -t' ' -11 -21 <(
      # extract the part inside `http://<here>/` and put it in front of the line
      # ip1:port1 25-08-2019_22.00.03 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ]
      <file1 sed -r 's@^(.*http://([^/]*).*)$@\2 \1@' | sort
    ) <(
      # extract the part inside `http://<here>/` and remove all the we are not interested in
      # ip1:port1 CS
      <file2 sed -r 's@http://([^/]*)/.*, (.*)@\1 \2@' | sort
    ) |
    # ip1:port1 25-08-2019_22.00.03 : Port port1 of URL http://ip1:port1/ is [ NOT OPEN ] CS
    # remove the leading ip1:port1
    cut -d' ' -f2- |
    # replace the trailing ` CS` with ` : CS`
    sed 's/[^ ]*$/: &/'
    

    【讨论】:

    • 嗨卡米尔,是否必须在脚本中输入文件,我的意思是输入会不时变化。我们不能只将输入作为文件提供吗?请输入会有所帮助。
    • 那么输入从哪里来?替换&lt;file1 用于重定向第一个文件,替换&lt;file2 用于重定向第二个文件。它们可以是 fifo,而不是普通文件。
    • 感谢卡米尔的提示输入,输入仅来自文件。我将按照建议尝试重定向,但是对于上述脚本,它实际上第一次工作现在给我错误“ sh -x merge_files.sh + cat + cat merge_files.sh:第 12 行:意外标记附近的语法错误 @ 987654326@join -t' ' -11 -21
    • 该文件使用bash扩展名,即。 &lt;(..) 进程重定向。你不能在sh 下运行它。您可以将其重写为在sh 下工作,创建两个fifo,将sed + sort 的输出重定向到fifos,然后将join 重定向到fifos。还要确保您的文件具有 unix 行结尾 dos2unix,并且您的脚本不是以 #!/bin/sh 开头,而是以 #!/bin/bash...
    • 谢谢卡米尔,我会试试的。
    【解决方案2】:

    使用cutpaste

    paste -d " : " file1 <(cut -s -d ',' -f2 file2)
    

    这将每行的两个文件行与: 连接起来。

    第二个文件被修改为只有基于逗号,的行的第二部分。

    【讨论】:

    • 嗨,它工作正常,但我面临不匹配条目的问题。即如果 file2 有更多条目,例如:ip1:port1/cs/personal、CS ip2:port2/cs/Satellite/out、CS_SAT ip3:port3/cs/Satellite/out、ED,它还会在文件末尾附加“ED”以及匹配的条目。我们能做些什么来只加入匹配的 ips 吗?它
    • 嗨 Oliv,此命令可用作命令行选项,但是当我尝试在 .sh 文件中运行此命令时,出现错误:意外标记附近的语法错误 `(' > 下面是我在其中使用命令的脚本:#!/bin/bash paste -d " : " wo_br.log merged_file.log。我尝试使用括号括起来,但是它不起作用,请帮忙?
    • @Novice 仅凭您的描述很难猜到...请提出另一个问题,并详细说明您所看到的错误。
    猜你喜欢
    • 1970-01-01
    • 2016-01-16
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2020-01-07
    • 2020-05-29
    • 1970-01-01
    相关资源
    最近更新 更多