【问题标题】:Select lines based on value in a column根据列中的值选择行
【发布时间】:2018-07-14 10:26:05
【问题描述】:

我有一个制表符分隔的表格,我想打印列“x”大于“Y”的所有行。我尝试使用下面的代码,但对使用 awk 很陌生,所以不确定如何根据列使用它。

awk '$X >= Y {print} ' Table.txt | cat > Wanted_lines 

Y 是从 1 到 100 的值。

如果输入如下所示,X 列是第二列。

1    30
2    50
3    100
4    100
5    80
6    79
7    90

想要的输出是:

3    100
4    100
5    80
7    90

文件的前两行是:

1   OTU1    243622  208679  121420  265864  0   0   2   0   0   11  1   5   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   839604  OTU1    -   Archaea 100%    Euryarchaeota   100%    Methanobacteria 100%    Methanobacteriales  100%    Methanobacteriaceae 100%    Methanobrevibacter  100%
2   OTU2    84366   120817  15834   74737   0   0   0   0   0   1   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   295755  OTU2    -   Archaea 100%    Euryarchaeota   100%    Methanobacteria 100%    Methanobacteriales  100%    Methanobacteriaceae 100%    Methanobrevibacter  100%

【问题讨论】:

  • 什么是“X”和“Y”? (您可以发布一些示例输入和所需的输出吗?)
  • 好的更新了解释,所以给出了更多细节。
  • 更新了 yopur 实际文件的答案

标签: bash awk


【解决方案1】:

第一

awk 的默认内部字段分隔符 (FS) 将适用于空格或制表符分隔的文件。

其次

awk '$x > FLOOR' Table.txt

其中$x 是目标列,FLOOR 是实际数字下限(即 5000 等...)

示例文件:awktest

500  100
400  1100
1000 400
1200 500


awk '$1 > 1000' awktest

1200   500

awk '$1 >= 1000' awktest

1000   400 
1200   500

因此,您应该能够使用关系表达式来打印 x > y 的行,格式如下:

awk '$x > $y' awktest

其中$x 是一个数字列,如$1 或其他。

其中$y 是一个数字列,如$2 或其他。

示例:

awk '$1 > $2' awktest

或者...

awk '$2 > $1' awktest

awk 数字是浮点数,因此您也可以比较小数。

【讨论】:

  • 我的意思是 X 是我希望从中获取比较数字的特定列,而 Y 是我只希望数字大于被采用的限制。
  • 我明白了。我做出了改变。希望对您有所帮助。
  • 我不明白你所说的“实际数字楼层”是什么意思,这是否是我想要作为选择值的值,例如如果 FLOOR 为 80,则将保留所有高于 80 的数字?
  • 是的。只需在上面出现 FLOOR 一词的地方替换数字 80。粗鲁,但有效。 :-) 我自己试过了,效果很好。
  • +1,但在这种情况下,我认为最好选择 x 和 FLOOR 的示例值,这样您就可以发布一个实际的工作示例。
【解决方案2】:

试试:

awk -v num_col=$X -v limit=$Y '$num_col + 0 >= limit + 0' Table.txt > Wanted_lines

例子:

$ cat Table.txt
1    30
2    50
3    100
4    100
5    80
6    79
7    90


$ X=2
$ Y=80
$ awk -v num_col=$X -v limit=$Y '$num_col + 0 > limit + 0' Table.txt
3    100
4    100
5    80
7    90

或者(hacky和不推荐)awk外壳可以这样破坏:

$  awk '$'"${X}"' + 0 >= '"${Y}"' + 0' Table.txt

这是您在实际文件中删除 % 符号所需要的:

$ awk -v num_col=43 -v limit=80 '{sub(/%/,"",$num_col)}$num_col + 0 >= limit + 0 ' Table.txt

【讨论】:

  • 这似乎创建了 Wanted_lines 文件,但它是空的,尽管我知道许多行在 X 列中的值大于 Y
  • 发布一段你的文件和解析的值
  • 好的,现在添加我实际文件的前两行。
  • 好的,要分析值的列?
  • 意识到我一直在陈述错误的列,但是即使使用正确的列,也只选择了 26 行,并且输出文件中只有少数行的值实际上超过了 80。
【解决方案3】:

所以...

  • '$X >= Y {print}' 是多余的,因为 awk 中的默认操作是打印。
  • | cat > file 是 UUOC。
  • 您的预期输出显示该值为 80 或更高的行。这个答案假定输出是您真正想要的,尽管缺少处理它的代码。
  • 我看不出您最后一个输入示例与事物的关系。您是否希望从该输入中获得特定的输出?

考虑:

$ awk '$X >= Y' X=2 Y=80 input.txt
3    100
4    100
5    80
7    90
$ awk '$X >= Y' X=2 Y=90 input.txt
3    100
4    100
7    90

上面的符号依赖于man awk的以下声明:

var=value 形式的任何文件 被视为分配,而不是文件名,并在 如果它是一个文件名,它会被打开的时间。

这在功能上等同于:

$ awk -v X=2 -v Y=80 '$X >= Y' input.txt

这些用于将 shell 变量放入 awk 脚本的符号中的任何一种都可以,我相信您遇到的任何 awk 版本(bsdawk、gawk、mawk)都应该同样处理好。

在 shell 脚本中,您可能会看到如下内容:

#!/usr/bin/env bash

if [[ $# != 2 ]]; then
  printf 'Please supply column and floor values as parameters.\n'
  exit 1
elif [[ $1 =~ [^0-9] ]] || [[ $2 =~ [^0-9] ]]; then
  printf 'Invalid parameters.\n'
  exit 1
fi

awk '$X >= Y' X="$1" Y="$2" input.txt

【讨论】:

    猜你喜欢
    • 2018-01-20
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多