【问题标题】:UNIX Grep FunctionUNIX grep 函数
【发布时间】:2014-02-28 09:30:06
【问题描述】:

我有一个包含制表符分隔列的文件。我想计算列中的唯一条目。但是,我想仅根据列中的输入来计算唯一性,并删除括号内的任何后续标记。

表格如下所示:

1 abc def xxx(sd) 5677
2 ddd hhh yyy(dd) 4321
3 fds ggf xxx(df) 5666

现在我想计算 xxxyyy 计算的唯一次数

所以预期的输出应该是2,而我得到的是3

我使用的代码是:

cut -f4 f.txt| sort| uniq -D |wc -l

【问题讨论】:

  • 请注意,sort 有一个 -k 选项,可让您按输入的指定部分进行排序,无需先输入 cut
  • 我不明白这会给 3. 当我运行它时,在更正 cut 命令后,它是 0,因为第四列对于所有行都是唯一的。
  • 列中要计算的唯一条目的字符数可能会有所不同。所以我想计算所有可能的条目,只要它们是唯一的。
  • 首数也是一列

标签: sorting unix grep cut uniq


【解决方案1】:

标准调试技术:单步执行,检查中间输出。

使用cut -f4,您将使用第四个字段,在本例中为:

xxx(sd)
yyy(dd)
xxx(df)

这是三个不同的条目,无论您如何排序。

详细说明我对sort-k 选项的评论,这给出了预期的“2”。 (我不确定你用-D 选项对uniq 做了什么。)

sort -k4.1,4.3 -u f.txt | wc -l

-k4.1,4.3 表示“按第 4 个字段的第 1 到第 3 个字符排序”,-u 表示“仅列出唯一行”,结果:

1   abc def xxx(sd) 5677
2   ddd hhh yyy(dd) 4321

第二个xxx 行不明显,未列出。


编辑

或者,您可以使用sed 提取输入行的所需部分,并将那个 提供给sort -u | wc -l。我还没有完全理解您输入的规格,所以我仍然在这里猜测:

sed "s/\(\S\+\s\+\)\{3\}\([^(]\+\).*/\2/" f.txt

解释:

  • \S\+\s\+ - 1..n 个非空格,后跟 1..n 个空格...
  • \(\S\+\s\+\)\{3\} - ...重复三遍...
  • \([^(]\+\) - ... 后跟 1..n 个非 ( 的字符...
  • .* - ...后面是任何东西...
  • /\2/ - ...替换为与第二组匹配的任何内容(1..n 个不是 ( 的字符)。

这给出了:

xxx
yyy
xxx

【讨论】:

  • 但我想要的是它应该告诉我 xxx 和 yyy 是独一无二的,而不是将括号条件作为独特事物的一部分。
  • 例如:cut -f4 给了我 xxx(sd) yyy(dd) xxx(df) xx(gg) yyz(rd)... 现在我想知道有多少个唯一的 xxx, yyy, xx, yyz 在那里。我不关心括号,我只想要括号前面的值重复的次数。
  • @Ankur:抱歉,我无法理解您的意图。据我所知,我的回答正是你所要求的。添加了一些解释以使其更清晰。
  • @Ankur:添加了使用 sed 的替代方案。您应该能够根据需要调整两种解决方案之一。
  • 输入可以是 2 个字符后跟括号或 6 个字符后跟括号。所以它可能是 xx(ds) 或 zzzzzz(hh)
【解决方案2】:

对于它的价值,你也可以试试这个,它会让你计算重复了多少次(xxx和yyy):

cat test.txt | awk {'print substr($4,0,4)'} | sort | uniq --count

如果你只需要不同的数量,只需添加wc -l,就像这样

cat test.txt | awk {'print substr($4,0,4)'} | sort | uniq --count | wc -l

我不确定这是否是最好的方法,但它确实有效。

让我知道你的想法。

【讨论】:

  • @Ankur:从您对我的回答的评论来看,只要括号前的字符少于或多于 3 个,awk 就会让您失望。您需要指定精确可能的输入,然后想出正确提取您想要计算的内容。尝试和错误不会削减它。
  • 注意cat file | awk '...'可以重写为awk '...' file
【解决方案3】:

您可以检查每个块出现的次数:

$ awk -F"[ (]" '{a[$4]++} END {for (i in a) print i, a[i]}' file
xxx 2
yyy 1

说明

  • -F"[ (]" 将字段分隔符设置为空格或(
  • {a[$4]++} 跟踪第 4 个字段出现的次数(基于这些字段分隔符,即 xxxyyy...)。
  • END {for (i in a) print i, a[i]} 打印结果。

如果您只是关心可以使用哪些不同的值:

$ awk -F"[ (]" '{a[$4]} END {for (i in a) print i}' file
xxx
yyy

说明

  • -F"[ (]" 将字段分隔符设置为空格或(
  • {a[$4]} 跟踪出现的第 4 个字段(基于这些字段分隔符,即 xxxyyy...)。
  • END {for (i in a) print i} 打印没有计数器的结果。

【讨论】:

    猜你喜欢
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多