【问题标题】:Comparing txt file to third column in a csv bash将txt文件与csv bash中的第三列进行比较
【发布时间】:2016-07-24 10:55:59
【问题描述】:

我对编程非常陌生,并决定学习 bash,因为我们处理一些基于 Linux/Unix 的日志服务器,因此编写脚本更容易一些。

我有一个 cvs 文件,其布局如下:

PC、用户、文件、路径 - 全部以逗号分隔。

我有一个以行分隔的文件名白名单。有些包括空格。

我的目标是将白名单与 csv 文件的第 3 列进行比较,并输出所有不匹配的行。我尝试了一个带有 if 语句的 while read 循环,但似乎无法让它工作。我已经做了一些 awk one 衬里,实际上从过去的 stackoverflow 帖子中得到了一个,该帖子输出了与白名单匹配的行,但我似乎无法弄清楚如何反转逻辑以使其工作。代码如下。

awk     'BEGIN{i=0}
       FNR==NR { a[i++]=$1; next }
        { for(j=0; j<i; j++)
            if(index($0,a[j]))
                {print $0;break}
        }' $whitelist $exestartup

我想坚持使用没有附加组件的基本 bash,并且不反对使用循环/if 语句而不是 awk one liner。

示例输入/输出:

白名单.txt

程序.exe
超级程序.exe
可能的程序.exe

exestartup.csv

Asset1,user1,potato.exe,c:\users\user1
Asset2,user2,program.exe,c:\users\user2
Asset3,user3,possible-program.exe,c:\users\user3
Asset4,user4,super program.exe,c:\users\user4

输出

Asset1,user1,potato.exe,c:\users\user1

【问题讨论】:

    标签: bash shell awk


    【解决方案1】:

    awk 来救援!

    awk -F, 'FNR==NR{a[$1]; next} !($3 in a)' whitelist exestartup
    

    将字段分隔符设置为逗号。加载所有白名单名称并与文件的 $3 字段进行比较,如果不匹配;打印。

    如果您发布示例输入和预期输出,您将获得更多答案和更好的建议。

    使用您的输入文件

    $ awk -F, 'FNR==NR{a[$1]; next} !($3 in a)' whitelist.txt exestartup.csv
    
    Asset1,user1,potato.exe,c:\users\user1
    

    如果您的 awk 已损坏并且字段值不相交,您可以恢复为 grep

    $ grep -vf whitelist.txt exestartup.csv
    
    Asset1,user1,potato.exe,c:\users\user1
    

    【讨论】:

    • 值得一提的是,在FNR==NR 块中使用$1 是正确的,只是因为使用了-F,。如果不存在,这只会将whitelist 中每行的第一个空格分隔字段分配给a
    • 感谢您的快速回复!似乎打印出几乎整个 csv 文件。使用示例输入/输出更新原始帖子。
    • 所以我之前看到过 awk 一个班轮并且之前使用过它,所以再次尝试它仍然无法使用我的 .txt 和 .csv 等以确保我不会发疯,我如上所述编写了我的示例输入/输出文件,实际上确实得到了我需要的答案。但它似乎在我的白名单和/或 csv 文件中格式化或关闭。为了安全起见,我在 nano 中重新输入了整个 whitelist.txt,但仍然只是打印出整个 csv 文件。我要疯了>
    • 调试!最好的学习方式。更改为 FNR==NR{a[$1]; print FILENAME, $1; next} {print FILENAME, $3}' 以打印 awk 看到的内容
    • 我就是这样做的,它会在调试中正确打印我的白名单和 csv 中的所有内容,但在原始 awk 上,它似乎忽略了 whitelist.txt,只是转储了 .csv作为输出。
    【解决方案2】:

    使用join:

    $ join -v 1 -t, -1 3 -2 1 -o 1.1,1.2,1.3,1.4 <(sort -t, -k3,3 exestartup.csv) <(sort whitelist.txt)
    Asset1,user1,potato.exe,c:\users\user1
    

    如果输入文件已经按匹配键排序(它们似乎不在您的示例中),则可能只是:

    $ join -v 1 -t, -1 3 -2 1 -o 1.1,1.2,1.3,1.4 exestartup.csv whitelist.txt
    

    【讨论】:

      【解决方案3】:

      此解决方案仅使用 Bash 3 内置函数:

      IFS=$'\n' read -d '' -r -a whitefiles < whitelist.txt
      
      while IFS= read -r csvline || [[ -n $csvline ]] ; do
          IFS=, read pc user file path <<< "$csvline"
          for wfile in "${whitefiles[@]}" ; do
              [[ $wfile == "$file" ]] && continue 2
          done
          printf '%s\n' "$csvline"
      done < exestartup.csv
      

      可以在 Bash 4 中实现更快、更简洁的解决方案,因为它具有关联数组。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-18
        • 2022-10-14
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        相关资源
        最近更新 更多