【问题标题】:Need to match a pattern occurrence only once in a file只需要在文件中匹配一次模式出现
【发布时间】:2013-05-18 10:27:11
【问题描述】:

我有多个带有某种模式的文件

ABCD  100
ABCD   200
EFGH    500
IJKL      50
EFGH    700
ABCD    800
IJKL    100

我只想匹配每个(ABCD/EFGH/IJKL)的出现一次,根据第 2 列中的最高数字进行排序

ABCD   800
EFGH    700
IJKL    100

我试过cat *txt | sort -k 1 |??

提前致谢

我的错,因为没有明确。为浪费您的时间而道歉。 下面是详细的例子。该文件有多个列。我用 awk 得到了需要的 并尝试了这个 cat *txt |awk '{print $3,$5}' |排序 -gr |less。现在我得到了基于数值排序的字符串。现在如何获取第一个匹配的 uniq 字符串。

<string>                <numeral>
abcde/efgh/ijkl/mnop    -450.00
dfgh/adas/gfda/adasd    -100.0
abcde/efgh/ijkl/mnop     -100.00
lk/oiojl/ojojl           -0.078
dfgh/adas/gfda/adasd   50.0
lk/oiojl/ojojl       -0.150
O/p needed
abcde/efgh/ijkl/mnop     -450.00
dfgh/adas/gfda/adasd    -100.0
lk/oiojl/ojojl       -0.150

【问题讨论】:

  • 两列之间的空格数对结果有影响吗?
  • 提供准确的输入和所需的输出会很有帮助。
  • 我的错。我认为能够从提示中破译:(

标签: perl bash shell


【解决方案1】:

您可以使用sort 两次:一次对数字进行排序,第二次对字符串进行stable 排序(以便最大的数字保留在前),删除重复项以丢弃重复具有较小数字的字符串。

sort -k2,2nr file.txt | sort -k1,1 -u --stable

【讨论】:

  • 太棒了,它完全按照预期工作并且非常干净。最后我用了这只猫 *txt | awk '{打印 $3,$5}' |排序-k2 -n |排序 -k1,1 -u --stable|较少的 。我只能以最低的数字(-ve)获得一次唯一的字符串。你能解释一下--stable。我找不到它的用途。谢谢
  • 由于sort -u 仅基于给定键删除重复项(通过保留第一个),我们希望确保即使我们在第一个字段上对整个列表进行排序,我们也希望确保例如“ABCD 800”没有排在“ABCD 200”之后。稳定的排序保证比较相等的项目(因此可以在输出中以任一顺序列出)保持与它们在输入中出现的顺序相同。并非所有排序算法都是稳定的;堆排序就是这样一个例子。 --stable 选项确保对输入应用稳定的排序。
【解决方案2】:

可以使用awk的关联数组,然后根据第2列排序:

awk '{ if ($2>arr[$1]) arr[$1]=$2} END{for (i in arr) print i, arr[i]}' file \
| sort -k2 -rn

【讨论】:

    【解决方案3】:
    cat *txt | perl -ane 'END{print "$_ $r{$_}\n" for sort keys %r} $_<$F[1] and $_=$F[1] for $r{$F[0]}'
    

    【讨论】:

      【解决方案4】:

      如果第一列总是4个字符,那么(根据abasu的建议)你可以使用uniq -w4

      cat *.txt | sort -gr | uniq -w4

      这以相反的数字顺序排序,('ABCD 800' 将在 'ABCD 100' 之前)并且在查找唯一行时仅考虑前 4 个字符。

      如果第一列不总是 4 个字符,您可以通过管道来回传递到 rev,并使用 uniq -f1 跳过第一个反向字段。

      cat *.txt | sort -gr | rev | uniq -f1 | rev

      如果你想定位一个特定的词,并得到最高的对应数字,你可以使用

      cat *.txt | sort -gr | grep 'ABCD' | head -n 1

      【讨论】:

      • 那不是 OP 要求的
      • 恐怕还是错了。 OP 需要 ABCD 800 EFGH 700 IJKL 100 而你有一个 UUoCA 朝你的方向前进......
      • 是的,刚刚看到。它适用于查找特定单词,例如“ABCD”,但要获得不同的列表是另一回事。
      • @ktm5124,我认为uniq会失败,因为它比较了行,现在ABCD 100ABCD 400不同,所以可能需要uniq -w4
      • @abasu:对,或者你可以做sort -gr | rev | uniq -f1;但如果总是 4 个字符,uniq -w4 最好。
      【解决方案5】:
      perl -anE'$h{$F[0]}=$F[1]if!exists$h{$F[0]}or$F[1]>$h{$F[0]}}{say"$_ $h{$_}"for keys%h'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-22
        相关资源
        最近更新 更多