awk - 比较每一行以找到重复的字段,并在行尾添加一些措辞

时间:2012-09-27 23:17:22

标签: text awk duplicates

我有一个像这个文件的文件,我正在尝试验证每一行的一个字段,并添加一些措辞,如果该字段在文件中早先有重复。

\\FILE04\BUET-PCO;\\SERVER24\DFS\SHARED\CORP\ET\PROJECT CONTROL OFFICE;/FS7_150a/FILE04/BU-D/PROJECT CONTROL OFFICE;10000bytes;9888;;;
\\FILE12\BUAG-GOLDMINE$;\\SERVER24\DFS\SHARED\CAN\AGENCY\GOLDMINE;/FS3_150a/FILE12/BU/AGENCY/GOLDMINE;90000bytes;98834;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;other stuff;;

在我的示例中,Line#3和#4具有相同的物理路径。 我想有一个脚本可以比较第三个字段/例如/ FS3_150a / FILE12 / BU / GB / BUSINTEG对同一个文件, 如果它找到完全匹配以打印类似“与线#相同的物理路径”的两种情况,

\\FILE04\BUET-PCO;\\SERVER24\DFS\SHARED\CORP\ET\PROJECT CONTROL OFFICE;/FS7_150a/FILE04/BU-D/PROJECT CONTROL OFFICE;10000bytes;9888;;;
\\FILE12\BUAG-GOLDMINE$;\\SERVER24\DFS\SHARED\CAN\AGENCY\GOLDMINE;/FS3_150a/FILE12/BU/AGENCY/GOLDMINE;90000bytes;98834;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;;;Same Physical Path as Line #4
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;other stuff;; Same Physical Path as Line #3

2 个答案:

答案 0 :(得分:2)

此代码处理问题的简化版本。它标识包含与字段3中的上一行相比重复值的每一行。它不处理具有后续重复项的行的标记。

awk -F';' '{ tag = ""
             if (field3[$3] != 0) tag = " Same physical path as line " field3[$3]
             else field3[$3] = NR
             printf "%s%s\n", $0, tag
           }' "$@"

可能有其他方法来组织它,但关键是使用关联数组field3来跟踪字段3中看到的名称以及首次看到给定名称的行号。这假设您正在处理单个输入文件。如果您必须处理多个文件,请查找FNR等(但您必须确定相同的名称是否可以出现在不同的文件中)。

它几乎按照给定的数据工作:

\\FILE04\BUET-PCO;\\SERVER24\DFS\SHARED\CORP\ET\PROJECT CONTROL OFFICE;/FS7_150a/FILE04/BU-D/PROJECT CONTROL OFFICE;10000bytes;9888;;;
\\FILE12\BUAG-GOLDMINE$;\\SERVER24\DFS\SHARED\CAN\AGENCY\GOLDMINE;/FS3_150a/FILE12/BU/AGENCY/GOLDMINE;90000bytes;98834;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;other stuff;; Same physical path as line 3

在第3行产生'标签'的困难在于预测未来;很难。要做到这一点,你必须将整个文件粘贴到内存中,密切关注字段3中给定值出现的行号(通常,这可能是一个广泛的行号列表),然后迭代通过数据和标记适当。非常非常难做;我更倾向于使用Perl来awk来完成这项工作,尽管在awk中正确组织数据可能也是可行的。

如果是我,我可以完成90%的工作;识别出具有重复的行。如果你想完成最后10%的工作,那么预计第一阶段计划的其他90%的时间都会花费。

答案 1 :(得分:1)

这是使用GNU awk的一种方式。这是一个有点hackish,YMMV。像:

一样运行
awk -f script.awk file.txt{,}

script.awk的内容:

BEGIN {
    FS = ";"
}

FNR==NR {
    array[$3]=array[$3] "#" NR
    next
}

{
    if ($3 in array && array[$3] ~ /#.#/) {
        copy = array[$3]
        sub("#"FNR, "", copy)
        printf "%s Same Physical Path as Line as %s\n", $0, copy
    }
    else {
        print
    }
}

结果:

\\FILE04\BUET-PCO;\\SERVER24\DFS\SHARED\CORP\ET\PROJECT CONTROL OFFICE;/FS7_150a/FILE04/BU-D/PROJECT CONTROL OFFICE;10000bytes;9888;;;
\\FILE12\BUAG-GOLDMINE$;\\SERVER24\DFS\SHARED\CAN\AGENCY\GOLDMINE;/FS3_150a/FILE12/BU/AGENCY/GOLDMINE;90000bytes;98834;;;
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;;; Same Physical Path as Line as #4
\\FILE12\BUGB-BUSINTEG$;\\SERVER24\DFS\SHARED\CAN\GB\BUSINTEG;/FS3_150a/FILE12/BU/GB/BUSINTEG;50000bytes;988822;other stuff;; Same Physical Path as Line as #3