cat/sed:日志文件片段的串联

cat/sed: concatenation of the fragments of the log filles

我有一个包含许多日志的文件夹。每个日志都有相似的格式。

这是log1

Finding intermodel H-bonds
Finding intramodel H-bonds
Constraints relaxed by 0.55 angstroms and 40 degrees
Models used:
    1.1 SarsCov2_Y6A_nsp5holo_rep1.pdb

6 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? SER 144 OG   /d UNL 1 S     /? SER 144 HG    3.940  3.529
/? HIS 163 NE2  /d UNL 1 S     no hydrogen      3.821  N/A
/? GLN 189 NE2  /d UNL 1 O     /? GLN 189 1HE2  3.178  2.453
/d UNL 1 N      /? THR 25 OG1  /d UNL 1 HN      2.755  2.270
/d UNL 1 N      /? CYS 44 O    /d UNL 1 HN      3.277  2.501
/d UNL 1 N      /? ARG 188 O   /d UNL 1 HN      3.056  2.055

log2

Finding intermodel H-bonds
Finding intramodel H-bonds
Constraints relaxed by 0.55 angstroms and 40 degrees
Models used:
    1.1 SarsCov2_06I_nsp5holo_rep1.pdb    
4 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? THR 26 N     /d UNL 1 O      /? THR 26 H      3.579  2.754
/? ASN 142 ND2  /d UNL 1 O      /? ASN 142 1HD2  3.250  2.324
/d UNL 1 N      /? THR 26 O     /d UNL 1 H       3.458  2.630
/d UNL 1 N      /? HIS 163 NE2  /d UNL 1 HN      3.222  2.456

这是日志 3:

Finding intermodel H-bonds
Finding intramodel H-bonds
Constraints relaxed by 0.55 angstroms and 40 degrees
Models used:
    1.1 SarsCov2_X7V_nsp5holo_rep1.pdb

2 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? GLN 189 NE2  /d UNL 1 O    /? GLN 189 1HE2  3.185  2.258
/d UNL 1 N      /? LEU 141 O  /d UNL 1 HN      2.868  1.958

我需要将所有日志融合在一起,仅采用从 # H-bonds 开始的字符串,并在同一行中添加初始文件的名称:

这是结合log1 -log 3产生的融合日志:

log 1: 6 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? SER 144 OG   /d UNL 1 S     /? SER 144 HG    3.940  3.529
/? HIS 163 NE2  /d UNL 1 S     no hydrogen      3.821  N/A
/? GLN 189 NE2  /d UNL 1 O     /? GLN 189 1HE2  3.178  2.453
/d UNL 1 N      /? THR 25 OG1  /d UNL 1 HN      2.755  2.270
/d UNL 1 N      /? CYS 44 O    /d UNL 1 HN      3.277  2.501
/d UNL 1 N      /? ARG 188 O   /d UNL 1 HN      3.056  2.055


log 2: 4 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? THR 26 N     /d UNL 1 O      /? THR 26 H      3.579  2.754
/? ASN 142 ND2  /d UNL 1 O      /? ASN 142 1HD2  3.250  2.324
/d UNL 1 N      /? THR 26 O     /d UNL 1 H       3.458  2.630
/d UNL 1 N      /? HIS 163 NE2  /d UNL 1 HN      3.222  2.456

log3: 2 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? GLN 189 NE2  /d UNL 1 O    /? GLN 189 1HE2  3.185  2.258
/d UNL 1 N      /? LEU 141 O  /d UNL 1 HN      2.868  1.958

我尝试过使用 CAT 的简单解决方案,但它无法正常工作,因为在每个日志中我都有不同的行数,而 TAIL 无法正确识别它:

for log in ${results}/*_rep"${i}".log; do
  log_name=$(basename "$log" .log)
  echo "$log_name" >> ${results}/combined.log
  cat $log | tail -n 10 >> ${results}/combined.log
done

我可以在某些特定的表达式中使用 cat 来识别行,或者我必须在 CAT 之前使用 SED 来从每个初始日志中删除未使用的行??

这个 awk 可以完成工作:

awk '
FNR==1 {p=0}
/^[0-9]+[[:space:]]+H-bonds$/ && FNR!=NR {printf "\n"}
/^[0-9]+[[:space:]]+H-bonds$/ {printf "log %d: ", ++c; p=1}
p==1'

对于每个给定的文件:

  • 每个新文件开始时停止打印。
  • 如果文件中的一行与 4 H-bonds 等的模式相匹配,如果它不是第一个文件,则打印一个空换行符。然后打印日志编号,并设置标志 p 以开始打印该日志文件。
  • 请注意,您可以省略第一个,而不是对同一个正则表达式进行两次测试,并将 if (FNR!=NR) {printf "\n"} 放在第二个的块内。这主要是关于可读性。
  • 我不确定文件名需要哪种模式表达式,*.log 就是一个例子。也许 "${results}"/*_rep*.log?

使用sed

$ for file in log{1..3}; do echo "${file##*/}: $(sed -n '/[0-9] H-bonds/,$p' "$file")"; echo ""; done
log1: 6 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? SER 144 OG   /d UNL 1 S     /? SER 144 HG    3.940  3.529
/? HIS 163 NE2  /d UNL 1 S     no hydrogen      3.821  N/A
/? GLN 189 NE2  /d UNL 1 O     /? GLN 189 1HE2  3.178  2.453
/d UNL 1 N      /? THR 25 OG1  /d UNL 1 HN      2.755  2.270
/d UNL 1 N      /? CYS 44 O    /d UNL 1 HN      3.277  2.501
/d UNL 1 N      /? ARG 188 O   /d UNL 1 HN      3.056  2.055

log2: 4 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? THR 26 N     /d UNL 1 O      /? THR 26 H      3.579  2.754
/? ASN 142 ND2  /d UNL 1 O      /? ASN 142 1HD2  3.250  2.324
/d UNL 1 N      /? THR 26 O     /d UNL 1 H       3.458  2.630
/d UNL 1 N      /? HIS 163 NE2  /d UNL 1 HN      3.222  2.456

log3: 2 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? GLN 189 NE2  /d UNL 1 O    /? GLN 189 1HE2  3.185  2.258
/d UNL 1 N      /? LEU 141 O  /d UNL 1 HN      2.868  1.958

如果我没有误解这个问题,一个简单的 grep 似乎就是你所追求的:

grep -EH '^([0-9]+\s+)?H-bonds($| \()|^/' log*

或者如果您需要精确格式:

for log in log*; do
    sed -n "s/^[0-9]\+\s\+H-bonds$/$log: &/; /^$log: /,${$s/$/\n/;p};" "$log"
done | sed '$d'

但我猜想额外的换行符是没有必要的,然后它就变得简单了:

for log in log*; do
    sed -n "s/^[0-9]\+\s\+H-bonds$/$log: &/; /^$log: /,$p" "$log"
done

如果需要额外解释,我很乐意return编辑此回复。

$ awk 'FNR==1{f=0} /^[0-9]+ H-bonds/{[=10=]=sep FILENAME": " [=10=]; sep=ORS; f=1} f' log?
log1: 6 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? SER 144 OG   /d UNL 1 S     /? SER 144 HG    3.940  3.529
/? HIS 163 NE2  /d UNL 1 S     no hydrogen      3.821  N/A
/? GLN 189 NE2  /d UNL 1 O     /? GLN 189 1HE2  3.178  2.453
/d UNL 1 N      /? THR 25 OG1  /d UNL 1 HN      2.755  2.270
/d UNL 1 N      /? CYS 44 O    /d UNL 1 HN      3.277  2.501
/d UNL 1 N      /? ARG 188 O   /d UNL 1 HN      3.056  2.055

log2: 4 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? THR 26 N     /d UNL 1 O      /? THR 26 H      3.579  2.754
/? ASN 142 ND2  /d UNL 1 O      /? ASN 142 1HD2  3.250  2.324
/d UNL 1 N      /? THR 26 O     /d UNL 1 H       3.458  2.630
/d UNL 1 N      /? HIS 163 NE2  /d UNL 1 HN      3.222  2.456

log3: 2 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
/? GLN 189 NE2  /d UNL 1 O    /? GLN 189 1HE2  3.185  2.258
/d UNL 1 N      /? LEU 141 O  /d UNL 1 HN      2.868  1.958

使用 SED 的“F”文件名选项

sed -i -n -s '1F;/[0-9] H-bonds/,$p' log* | sed -i -s '1N;s/\n/: /' log*

解释:
-i ---> 就地
-n ---> 禁用输出
-s ----> 将所有输入文件视为单独文件
1F ----> 打印第一行读取的输入文件名
/[0-9] H-bonds/,$p ---> 打印模式范围 N;s/\n: / ---> 合并前两行添加:

sed 的一个缺陷是“F”选项直接将文件名输出到 stdout 而不是模式 space 并且不能在一个 liner 中使用它