2

我有一些包含以下数据的文件:

 160-68 160 68 B-A 0011 3.80247
 160-68 160 68 B-A 0022 3.73454
 160-69 160 69 B-A 0088 2.76641
 160-69 160 69 B-A 0022 3.54446
 160-69 160 69 B-A 0088 4.24609
 160-69 160 69 B-A 0011 3.97644
 160-69 160 69 B-A 0021 1.82292

我需要在第 5 列的数组中提取具有任何值(可以是负数:ex -12222)的行。

输出 [0088, 0021]:

160-69 160 69 B-A 0088 2.76641
160-69 160 69 B-A 0088 4.24609
160-69 160 69 B-A 0021 1.82292

我目前正在使用 Ruby 执行此操作,但是有没有办法使用 Bash 更快地完成此操作?

谢谢。

4

3 回答 3

4

bash 不太可能比 ruby​​ 快:bash 通常很慢。我会选择 awk 或 perl

awk -v values="0088 0021" '
    BEGIN {
        n = split(values, a)
        for (i=1; i<=n; i++) b[a[i]]=1
    }
    $5 in b
' file
perl -ane 'BEGIN {%v = ("0088"=>1, "0021"=>1)} print if $v{$F[4]}' file
于 2016-01-30T22:45:19.453 回答
1

这是一个基于 egrep 的解决方案。

假设特殊值数组以简单的 CSV 字符串形式给出,例如

A="0088,0021"

然后 egrep 的以下调用将选择所需的行:

egrep "( [^ ]+){3} ($(tr , '|' <<< "$A")) "

在实践中,修改上面的正则表达式以使其在输入格式方面不那么脆弱可能会更好。

如果数组 ($A) 的元素包含 egrep 的特殊字符(如方括号、圆括号等),则需要小心转义它们。这可以以编程方式完成,例如

A=$(sed 's/[]\.|$(){}?+*^]/\\&/g' <<< "$A")

另请参阅下面的评论。

于 2016-01-31T03:47:18.160 回答
-1

另一种解决方案

     #!/bin/bash
     for i in "$@"
         do 
         while read column
         do
            arr=(${column})
            if [ ${arr[4]} = $i ]
            then
                echo $column
            fi
         done < input.txt
    done

其中 input.txt 是数据文件,您将此脚本称为 ./scriptname 0088 0021

于 2016-01-31T06:14:17.123 回答