繁体   English   中英

bash循环并提取txt文件的片段

[英]bash looping and extracting of the fragment of txt file

我正在处理位于工作目录中的大量 dlg 文本文件的分析。 每个文件都有一个表格(通常位于日志的不同位置),格式如下:

文件 1:

    CLUSTERING HISTOGRAM
    ____________________


________________________________________________________________________________
     |           |     |           |     |
Clus | Lowest    | Run | Mean      | Num | Histogram
-ter | Binding   |     | Binding   | in  |
Rank | Energy    |     | Energy    | Clus|    5    10   15   20   25   30   35
_____|___________|_____|___________|_____|____:____|____:____|____:____|____:___
   1 |     -5.78 |  11 |     -5.78 |   1 |#
   2 |     -5.53 |  13 |     -5.53 |   1 |#
   3 |     -5.47 |  17 |     -5.44 |   2 |##
   4 |     -5.43 |  20 |     -5.43 |   1 |#
   5 |     -5.26 |  19 |     -5.26 |   1 |#
   6 |     -5.24 |   3 |     -5.24 |   1 |#
   7 |     -5.19 |   4 |     -5.19 |   1 |#
   8 |     -5.14 |  16 |     -5.14 |   1 |#
   9 |     -5.11 |   9 |     -5.11 |   1 |#
  10 |     -5.07 |   1 |     -5.07 |   1 |#
  11 |     -5.05 |  14 |     -5.05 |   1 |#
  12 |     -4.99 |  12 |     -4.99 |   1 |#
  13 |     -4.95 |   8 |     -4.95 |   1 |#
  14 |     -4.93 |   2 |     -4.93 |   1 |#
  15 |     -4.90 |  10 |     -4.90 |   1 |#
  16 |     -4.83 |  15 |     -4.83 |   1 |#
  17 |     -4.82 |   6 |     -4.82 |   1 |#
  18 |     -4.43 |   5 |     -4.43 |   1 |#
  19 |     -4.26 |   7 |     -4.26 |   1 |#
_____|___________|_____|___________|_____|______________________________________

目的是遍历所有 dlg 文件并从表中取出与更宽集群相对应的单行(直方图列中的斜线数量更大)。 在上表的示例中,这是第三行。

   3 |     -5.47 |  17 |     -5.44 |   2 |##

然后我需要将此行与日志文件的名称(应在该行之前指定)一起添加到 final_log.txt 中。 所以最后我应该有以下格式的东西(对于 3 个不同的日志文件):

"Name of the file 1": 3 |     -5.47 |  17 |     -5.44 |   2 |##
"Name_of_the_file_2": 1 |     -5.99 |  13 |     -5.98 |  16 |################
"Name_of_the_file_3": 2 |     -4.78 |  19 |     -4.44 |   3 |###

我的 BASH 工作流程的一个可能模型是:

#!/bin/bash
do
  file_name2=$(basename "$f")
  file_name="${file_name2/.dlg}"
  echo "Processing of $f..."
  # take a name of the file and save it in the log
  echo "$file_name" >> $PWD/final_results.log
  # search of the beginning of the table inside of each file and save it after its name
  cat $f |grep 'CLUSTERING HISTOGRAM' >> $PWD/final_results.log
  # check whether it works
  gedit $PWD/final_results.log
done

在这里,我需要替换 echo 和 grep 的组合以获取表格的选定部分。

您可以使用这个,预计速度足够快。 除了表格之外,文件中的额外行预计不会成为问题。

grep "#$" *.dlg | sort -rk11 | awk '!seen[$1]++'

grep获取所有直方图行,然后按最后一个字段以相反的顺序排序,这意味着最多#行在顶部,最后awk删除重复项。 请注意,当grep解析多个文件时,默认情况下-H在行的开头打印文件名,因此如果您对一个文件进行测试,请使用grep -H

结果应该是这样的:

file1.dlg:   3 |     -5.47 |  17 |     -5.44 |   2 |##########
file2.dlg:   3 |     -5.47 |  17 |     -5.44 |   2 |####
file3.dlg:   3 |     -5.47 |  17 |     -5.44 |   2 |#######

这是在文件中有许多相等的最大行的情况下获得第一次出现的修改:

grep "#$" *.dlg | sort -k11 | tac | awk '!seen[$1]++'

我们用反转文件流的“tac”命令替换了 sort 中的 reversed 参数,所以现在对于任何相等的行,初始顺序被保留。


第二种解决方案

这里只使用 awk:

awk -F"|" '/#$/ && $NF > max[FILENAME] {max[FILENAME]=$NF; row[FILENAME]=$0}
           END {for (i in row) print i ":" row[i]}' *.dlg

更新:如果您从不同的目录执行它并且只想保留每个文件的基本名称,请删除路径前缀:

awk -F"|" '/#$/ && $NF > max[FILENAME] {max[FILENAME]=$NF; row[FILENAME]=$0}
           END {for (i in row) {sub(".*/","",i); print i ":" row[i]}}'

作为 awk 脚本可能更有意义。

在输入文件中出现平局的情况下,这将选择具有最宽直方图的第一行。

#!/bin/bash

awk 'FNR == 1 { if(sel) print sel; sel = ""; max = 0 }
   FNR < 9 { next }
   length($10) > max { max = length($10); sel = FILENAME ":" $0 }
   END { if (sel) print sel }' ./"$prot"/*.dlg

这假设直方图始终是第十个字段; 如果您的输入格式比您显示的肿块更混乱,则可能会适应口味。

更详细地说,第一行在每个输入文件的第一行触发。 如果我们收集了前一行(意味着这不是第一个输入文件),打印它,然后重新开始。 否则,初始化第一个输入文件。 sel设置为selmax设置为零。

第二行跳过包含标题的第 1-8 行。

第三行检查当前行的直方图是否长于max 如果是,将max更新为该直方图的长度,并记住sel的当前行。

最后一行是我们处理完所有文件时的溢出。 我们从来没有从最后一个文件中打印sel ,所以也打印它,如果它被设置了。

如果你的意思是说我们应该找到CLUSTERING HISTOGRAM和表格末尾之间的线,我们可能应该有更多关于周围线是什么样子的信息。 不过,也许是这样的;

awk '/CLUSTERING HISTOGRAM/ { if (sel) print sel; looking = 1; sel = ""; max = 0 }
   !looking { next }
   looking > 1 && $1 != looking { looking = 0; nextfile }
   $1 == looking && length($10) > max { max = length($10); sel = FILENAME ":" $0 }
   END { if (sel) print sel }' ./"$prot"/*.dlg

这台looking到1的时候,我们看到CLUSTERING HISTOGRAM ,然后计数到第一线looking不再增加。

我建议使用awk处理:

for i in $FILES
do
    echo -n \""$i\": "
    awk 'BEGIN {
           output="";
           outputlength=0
         }
         /(^ *[0-9]+)/ {                                    # process only lines that start with a number
           if (length(substr($10, 2)) > outputlength) {     # if line has more hashes, store it
             output=$0;
             outputlength=length(substr($10, 2))
           }
         }
         END {
           print output                                     # output the resulting line
         }' "$i"
done

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM