根据shell脚本中的列值创建文件

时间:2018-05-31 14:19:27

标签: shell

我有大文件,每行有五列。像这样:

1234   58493  12334 98034 2344
9873   58493  4535  3453  64435
32453  58493  76546 1344  67867
7456    3457  234   2346  34547
4234    3457  7809  3452  12456
1234    3457  5345  1234  7548
...

我需要处理此文件,根据第二列生成其他文件。因此,在上面的示例中,我想生成以下两个文件。

58493.txt

1234   58493  12334 98034 2344
9873   58493  4535  3453  64435
32453  58493  76546 1344  67867

3457.txt

7456    3457  234   2346  34547
4234    3457  7809  3452  12456
1234    3457  5345  1234  7548

我正在使用此脚本。

while read LINE
do
    varible=`echo $LINE | cut -d " " -f 2`
    echo $LINE >> $OUTPUT/$variable.txt
done < $INPUT/file.txt

问题是,这个脚本在时间上是不可行的。

有人知道更好的方法吗?

非常感谢!

1 个答案:

答案 0 :(得分:0)

我不能说这会更快,但你可以避免子shell,可执行调用(cut),变量赋值和每个发生的开放附加关闭循环线。根据您的描述,我可以通过以下方式解决问题:

  # Step 1: get all of the unique identifiers
$ UNIQ_IDS="$(awk '{print $2}' < big_file | sort | uniq)"

  # Step 2: iterate the identifiers, pull out the matching lines
$ for i in $UNIQ_IDS; do
    grep -E "^\\S+ +$i " > $i.txt
  done

这种方法对你的方法的缺点是,你的工作将在一个无限大的文件上工作,因为它会立即做出决定。然而,该方法首先对数据进行预处理,然后对文件N进行多次迭代。因此,根据您的问题的细节,这可能不是一个胜利。

这是如何工作的?鉴于上面的例子:

  • awk '{print $2}' < big_file仅打印其输入的第二列,在本例中为big_file
  • 该输出通过管道传输(|)到sort,这是同名的,确保所有相似项目组合在一起。
  • 已排序的输出通过管道传输(|)到uniq,这会从流中删除所有重复项(首先需要排序;我将在阅读手册页时将其作为练习留下{ {1}}和man sort)。
  • 最后,所有这些都是在&#34;子shell&#34;中执行的。 man uniq,输出存储在$( ... )中。这个变量现在成立:

    UNIQ_IDS
然后,第2部分可能会提供加速,因为它只能写入每个文件一次<(而不是每行$ echo $UNIQ_IDS 3457 58493 打开和关闭一个文件) ,并利用用C语言编写并为此目的而制作的big_file。最后,grep是什么?那是regular expression,在这种情况下,说:

  • -E "^\\S+ +$i ") - 锚定到行的开头,
  • ^) - 匹配第一个非空白字符(第一列);注意这里没有双反斜杠,如下所述
  • \S+) - 匹配一个或多个空格字符
  • +) - 匹配您的确切循环变量,例如$i
  • 3457) - 匹配最后一个空格,以便分隔第二列

因此,循环的第一次迭代将变为(有效):

因此,在shell解释之后,发送到grep -E "^\\S+ +3457 " > 3457.txt 的实际正则表达式为:

grep

(空格更改为下划线[^\S+_+3457_ ]仅供此处演示。)