서로 다른 폴더에 있는 여러 로그 파일에서 문자열 추출

서로 다른 폴더에 있는 여러 로그 파일에서 문자열 추출

상위 폴더 안에는 많은 하위 폴더가 있고 각 하위 폴더 안에는 로그 파일이 있습니다. 로그 파일에는 다음과 같은 많은 데이터가 있습니다.

>  Rotational constants (GHZ):           0.0423083           0.0029364  
> 0.0027927  Standard basis: 6-31G(d,p) (6D, 7F)  There are  1566 symmetry adapted cartesian basis functions of A   symmetry.  There are
> 1566 symmetry adapted basis functions of A   symmetry.   1566 basis
> functions,  3052 primitive gaussians,  1566 cartesian basis functions 
> 355 alpha electrons      355 beta electrons
>        nuclear repulsion energy     15971.0567247177 Hartrees.  NAtoms=  130 NActive=  130 NUniq=  130 SFac= 1.00D+00 NAtFMM=   60
> NAOKFM=T Big=T  Integral buffers will be    131072 words long. 
> Raffenetti 2 integral format.  Two-electron integral symmetry is
> turned on.  One-electron integrals computed using PRISM.  NBasis= 
> 1566 RedAO= T EigKep=  2.31D-04  NBF=  1566  NBsUse=  1566 1.00D-06
> EigRej= -1.00D+00 NBFU=  1566  Initial guess from the checkpoint file:
>     > 0.000000    0.000000    0.000000
>          Rot=    1.000000   -0.000006    0.000001   -0.000001 Ang=   0.00 deg.  Requested convergence on RMS density matrix=1.00D-08 within 128 cycles.  Requested convergence on MAX density matrix=1.00D-06. 
> Requested convergence on             energy=1.00D-06.  No special
> actions if energy rises.  SCF Done:  E(RB3LYP) =  -8526.66394979    
> A.U. after    6 cycles
>             NFock=  6  Conv=0.72D-08     -V/T= 2.0055  Calling FoFJK, ICntrl=      2127 FMM=T ISym2X=0 I1Cent= 0 IOpClX= 0 NMat=1 NMatS=1
> NMatT=0.

예를 들어 SCF Done: E(RB3LYP) = -8526.66394979위의 텍스트를 보고 있습니다. =각 파일의 변경된 값입니다. 나에게 필요한 것은 모든 값을 추출하여 상위 폴더의 텍스트 파일에 넣는 것입니다. 예를 들어 bar, baz, foo라는 3개의 폴더가 있습니다. 이제 다음 결과가 필요합니다.

bar : -8526.66394979
baz : -112232.123391
foo : 12312313:34574

다음 스크립트를 실행하면 하나의 값만 갖게 됩니다(예: -8526.66394979). 이 문제를 해결하는 데 도움을 주실 수 있나요?

#!/bin/bash

for file_name in *
do

cd $file_name

EE=$(grep -i 'scf done' *.log | tail -1 | awk 'NR==1 {print $5}')

echo "Electronic Energy : $EE" | column -t -s ":"  > ${file_name%%.*}.txt

mv ${file_name%%.*}.txt ../

done

답변1

디렉터리당 하나의 로그 파일만 있고 해당 로그 파일의 마지막 값을 유지하고 이를 디렉터리 이름과 함께 텍스트 파일에 저장하려는 경우 다음을 수행할 수 있습니다.

for dir in */; do
    grep -i 'scf done' "$dir"/*.log | 
        awk 'END{print "Electronic Energy : "$5}' |
            column -t -s ":" > "${dir///}".txt
done

예를 들어 다음 설정을 사용했습니다.

$ tree
.
├── dir1
│   └── file.log
├── dir10
│   └── file.log
├── dir2
│   └── file.log
├── dir3
│   └── file.log
├── dir4
│   └── file.log
├── dir5
│   └── file.log
├── dir6
│   └── file.log
├── dir7
│   └── file.log
├── dir8
│   └── file.log
└── dir9
    └── file.log

각각은 file.log다음을 포함합니다:

$ cat dir1/file.log 
a b scf done 123

for위 루프를 실행하면 다음과 같은 결과가 발생합니다.

$ ls *txt
dir10.txt  dir1.txt  dir2.txt  dir3.txt  dir4.txt  dir5.txt  dir6.txt  dir7.txt  dir8.txt  dir9.txt

각 항목에는 다음이 포함됩니다.

$ cat dir1.txt 
Electronic Energy    123

그래도 문제가 해결되지 않으면 질문을 업데이트하고 관련 디렉터리 구조, 파일 이름, 샘플 입력 및 예상 출력을 보여주세요.

답변2

나는 이것을 준비했다 :

#!/bin/bash



for dir in */; do
    grep -i 'scf done' "$dir"/*.log | 
         awk 'END{print ""$5}'|
            column -t -s ":" > "${dir///}".tmp
done


for file_name in *.tmp
 do
    echo "${file_name%%.*} : " 
    cat "$file_name"    
      
    
done > tmp


awk 'NR%2{printf "%s ",$0;next;}1' tmp > tmp2
        sort -k 3 tmp2 > Energy.txt

rm *.tmp tmp tmp2
cat Energy.txt

그것은 작동하고 필요한 모든 것을 다룹니다. 그러나 저는 작동할 수 있는 명령을 사용하여 코딩하는 높은 수준의 방법을 찾고 있습니다.

답변3

디렉터리 구조를 올바르게 이해하고 재현하기를 바랍니다. 다음을 시도해 보세요.

awk '/SCF Done/ {print FILENAME ": " $NF}' */*.log
bar/b1.log: -8526.66394979
baz/b2.log: -7777777.22222
baz/b2.log: -112232.123391
foo/f3.log: -7777777.22222
foo/f3.log: 12312313.34574

디렉토리만 원하는 경우 결과 배열의 첫 번째 요소를 split사용하십시오 . FILENAME각 파일의 마지막 항목만 필요한 경우 다음을 시도하십시오.

awk '/SCF Done/ {print FILENAME ": " $NF}' */*.log | tac | sort -u -k1,1
bar/b1.log: -8526.66394979
baz/b2.log: -112232.123391
foo/f3.log: 12312313.34574

에서 정리하는 것보다 이것이 더 쉽고 간단합니다 awk.

관련 정보