【问题标题】:Awk or Sed commands to remove duplicates from the CSV file用于从 CSV 文件中删除重复项的 awk 或 Sed 命令
【发布时间】:2020-03-30 23:54:42
【问题描述】:

我确实有生成的 CSV 文件,其中包含重复值。我想使用 AWK 或 Sed 命令删除/删除重复值。

实际输出

10.135.83.48,9042
10.135.83.46,9042
10.135.83.44,9042
10.5.197.25,10334
10.39.8.166,1500
10.135.83.48,9042
10.135.83.46,9042
10.135.83.44,9042
https://t-mobile.com,443
https://t-mobile.com,443
http://localhost:5059/abc/token,80

预期输出

  10.135.83.48,9042
    10.135.83.46,9042
    10.135.83.44,9042
    10.5.197.25,10334
    10.39.8.166,1500
https://t-mobile.com,443
http://localhost:5059/abc/token,80

从几个属性文件中我得到了这个输出。下面是我正在尝试的脚本

#!/bin/bash
for file in $(ls); 
do 
#echo  " --$file -- "; 
grep -P  '((?<=[^0-9.]|^)[1-9][0-9]{0,2}(\.([0-9]{0,3})){3}(?=[^0-9.]|$)|(http|ftp|https|ftps|sftp)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/+#-]*[\w@?^=%&/+#-])?|\.port|\.host|contact-points|\.uri|\.endpoint)' $file|grep '^[^#]' |awk '{split($0,a,"#"); print a[1]}'|awk '{split($0,a,"="); print a[1],a[2]}'|sed 's/^\|#/,/g'|awk '/http:\/\//  {print $2,80}
       /https:\/\// {print $2,443}
       /Points/     {print $2,"9042"}
       /host/       {h=$2}
       /port/       {print h,$2; h=""}'|awk -F'[, ]' '{for(i=1;i<NF;i++){print $i,$NF}}'|awk 'BEGIN{OFS=","} {$1=$1} 1'|sed '/^[0-9]*$/d'|awk -F, '$1 != $2' 
done |awk '!a[$0]++' 
#echo "Done."
stty echo
cd ..

awk '!a[$0]++' --> 这是我试图与上述脚本结合的命令。单独此命令正在工作。但是当我尝试与上述脚本结合时,它没有按预期工作。

提前感谢您的帮助。

【问题讨论】:

  • 这应该在循环内
  • 我很想知道实际输入文件的格式......在我看来,有很多 grepping & awking 正在进行......
  • 如果顺序无关紧要,只需sort -u 工作,顺便说一句。
  • for file in $(ls); 不要那样做。使用for file in *; 更多信息请参见mywiki.wooledge.org/ParsingLs

标签: linux shell awk sed


【解决方案1】:

试试

#!/bin/bash
for file in *; 
do 
#echo  " --$file -- "; 
grep -P  '((?<=[^0-9.]|^)[1-9][0-9]{0,2}(\.([0-9]{0,3})){3}(?=[^0-9.]|$)|(http|ftp|https|ftps|sftp)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/+#-]*[\w@?^=%&/+#-])?|\.port|\.host|contact-points|\.uri|\.endpoint)' $file|grep '^[^#]' |awk '{split($0,a,"#"); print a[1]}'|awk '{split($0,a,"="); print a[1],a[2]}'|sed 's/^\|#/,/g'|awk '/http:\/\//  {print $2,80}
       /https:\/\// {print $2,443}
       /Points/     {print $2,"9042"}
       /host/       {h=$2}
       /port/       {print h,$2; h=""}'|awk -F'[, ]' '{for(i=1;i<NF;i++){print $i,$NF}}'|awk 'BEGIN{OFS=","} {$1=$1} 1'|sed '/^[0-9]*$/d'|awk -F, '$1 != $2' | awk '!a[$0]++'  
done 
#echo "Done."
stty echo
cd ..

【讨论】:

    【解决方案2】:

    解决这个问题的最简单方法(或最简单的方法之一)是保留一个由已看到的记录索引的数组。如果记录不在seen 数组中,则添加它并打印记录。如果是,则跳过记录,例如

    awk '$0 in seen{next}; {seen[$0]++}1' file
    

    使用/输出示例

    在名为dupes 的文件中输入您的内容,您将拥有:

    $ awk '$0 in seen{next}; {seen[$0]++}1' dupes
    10.135.83.48,9042
    10.135.83.46,9042
    10.135.83.44,9042
    10.5.197.25,10334
    10.39.8.166,1500
    https://t-mobile.com,443
    http://localhost:5059/abc/token,80
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -E 'H;x;s/((\n[^\n]+)(\n.*)*)\2$/\1/;x;$!d;x;s/.//' file1
      

      将当前行附加到保留空间 (HS),如果它是重复的,则将其删除。

      在文件末尾,交换到 HS,删除第一个字符(这是一个换行符)并打印结果。

      注意这将删除重复项但保留原始顺序。

      【讨论】:

        猜你喜欢
        • 2014-10-13
        • 2020-05-18
        • 2014-02-11
        • 2023-03-05
        • 2014-01-30
        • 1970-01-01
        • 2018-03-24
        • 2016-02-04
        • 2021-08-20
        相关资源
        最近更新 更多