Text Awk-比较每一行以找到一个重复的字段,并在行尾添加一些文字

Text Awk-比较每一行以找到一个重复的字段,并在行尾添加一些文字,text,awk,duplicates,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

我有一个类似于此文件的文件,我试图验证每行的一个字段,如果该字段在文件前面有重复项,则添加一些措辞

\\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;;
在我的示例中,第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

这段代码处理问题的简化版本。它标识与字段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%的时间。

这里有一种使用
GNU awk
的方法。这有点老套,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

如果物理路径出现超过2次,应该怎么办?您是否希望
与第#3,#4行相同的物理路径
?@beny23它应该说明是否至少与任何其他行重复,如果可能,与所有行重复,但如果已经标记,则对我来说就足够了。我使用的是Windows的gawk端口版本,我尝试使用此代码。但它似乎失败了,我尝试了cygwin也运行,但没有发现任何重复match@Eduardo:我可以确认这在linux环境中有效。我使用的是
gnuawk4.0.1
。我强烈建议您安装linux发行版,如果没有windoze,请删除它。您在cygwin上使用的是哪个版本的GNU awk?可能尝试:
awk-f script.awk file.txt file.txt
谢谢Steve,cygwin GNU awk 4.0.1上的awk版本我用那种方式尝试过,但似乎失败了$awk-f script.awk dfsvshares.csv newfile.csv awk:script.awk:7:fatal:无法打开文件
newfile.csv'进行读取(没有这样的文件或目录)$awk-f script.awk dfsvshares.csv newfile.csv awk:script.awk:7:fatal:无法打开文件
newfile.csv'进行读取(没有此类文件或目录)当我运行$awk-f script.awk dfsvshares.csv时,它将完成,但标准输出上没有显示任何内容,我将查看是否可以找到Linux主机here@Eduardo:您需要指定文件名两次
awk-f script.awk file.txt{,}
实际上是
awk-f script.awk file.txt file.txt的缩写。为了获得所需的输出,文件必须读取两次,因此我们必须告诉
awk
读取同一文件两次。您不应该指定两个不同的文件名,也不应该只列出一次文件名。@Eduardo:谢谢,很高兴我能帮忙:-)