나는 파일을 가지고 있습니다 DEMLIR-GEO_OPT-1-distance-1.coordLog
:
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.944776 0.190651 1.602108 |r| = 1.869679
r(2,5) = -0.693580 -0.927860 -1.000974 |r| = 1.530989
r(2,8) = 1.618580 0.570765 -0.688275 |r| = 1.849134
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.945905 0.187745 1.601950 |r| = 1.869821
r(2,5) = -0.692409 -0.928976 -1.001505 |r| = 1.531483
r(2,8) = 1.618487 0.572023 -0.688769 |r| = 1.849626
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.946708 0.186226 1.601724 |r| = 1.869881
r(2,5) = -0.691970 -0.929421 -1.002033 |r| = 1.531900
r(2,8) = 1.618395 0.572685 -0.688576 |r| = 1.849678
파일의 각 줄을 읽고 패턴이 포함되어 있으면 r(1,5)
다음 값을 인쇄하고 싶습니다 |r| =
. 지금까지 다음 코드를 작성했습니다.
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
exec 0<"DEMLIR-GEO_OPT-1-distance-1.coordLog"
while read -r line
do
for j in $(seq 0 2)
do
if [[ "$line" == *"r(1,5)"* ]] ; then
dist1=$(gawk 'BEGIN{FS="|r| ="} {print $2}' | tr -s " ")
elif [[ "$line" == *"r(2,5)"* ]] ; then
dist2=$(gawk 'BEGIN{FS="|r| ="} {print $2}' | tr -s " ")
elif [[ "$line" == *"r(2,8)"* ]] ; then
dist3=$(gawk 'BEGIN{FS="|r| ="} {print $2}' | tr -s " ")
fi
printf "%-3f %-3f %-3f %-3f\n" "1.$j" "$dist1" "$dist2" "$dist3"
done
done>DEMLIR_task.txt
하지만 다음과 같은 오류가 발생합니다.
dist1: unbound variable
1.0 라인에는 도달하지 않지만 "1.$j"
오류도 발생한다는 것을 알고 있습니다.
나는 또한 sed
내가 원하는 것을 얻으려고 노력했는데, 그것은 다음과 같습니다:
sed -n '/r(1,5)/p' DEMLIR-GEO_OPT-1-distance-1.coordLog> new
sed -i 's/^.*|r| =//' new
그러면 새 파일에 그 이후의 값이 인쇄되고 |r| =
, if 문에서 볼 수 있듯이 다른 두 조건에 대해서도 동일한 작업을 수행해야 한다는 점을 고려하면 필요하지 않은 파일이 너무 많아지게 됩니다. 나는 그것을 원하지 않습니다.
나는 첫 번째 작업 방식을 원합니다. 어떻게 해야 합니까?
편집하다
r(1,5)
0,1,2의 거리를 첫 번째 열, 두 번째, r(2,5)
세 번째, 네 번째 열에 인쇄 하고 싶습니다. 새 파일을 만들거나 원본 파일을 변경하지 않고 이 작업을 수행하고 싶습니다. 내가 원하는 출력은 다음과 같습니다.r(2,8)
DEMLIR_task.txt
0 1.869679 1.530989 1.849134
1 1.869821 1.531483 1.849626
2 1.869881 1.531900 1.849678
답변1
가능한 솔루션은 awk
에만 있습니다. 나는 하나를 만들었습니다 prg.awk
:
BEGIN { j=0; }
{
if ( $1 == "r(1,5)" )
{
dist1=$8;
}
if ( $1 == "r(2,5)" )
{
dist2=$8;
}
if ( $1 == "r(2,8)")
{
dist3=$8;
print j": "dist1" "dist2" "dist3;
++j;
}
}
콘텐츠 file.txt
:
yurijs-MacBook-Pro:bash yurij$ cat ./file.txt
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.944776 0.190651 1.602108 |r| = 1.869679
r(2,5) = -0.693580 -0.927860 -1.000974 |r| = 1.530989
r(2,8) = 1.618580 0.570765 -0.688275 |r| = 1.849134
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.945905 0.187745 1.601950 |r| = 1.869821
r(2,5) = -0.692409 -0.928976 -1.001505 |r| = 1.531483
r(2,8) = 1.618487 0.572023 -0.688769 |r| = 1.849626
REQUESTED STRUCTURE DATA
Distance vector r(i,j) between the atom i and j in ANGSTROM
r(1,5) = 0.946708 0.186226 1.601724 |r| = 1.869881
r(2,5) = -0.691970 -0.929421 -1.002033 |r| = 1.531900
r(2,8) = 1.618395 0.572685 -0.688576 |r| = 1.849678
프로그램을 실행합니다:
yurijs-MacBook-Pro:bash yurij$ awk -f prg.awk ./file.txt
0: 1.869679 1.530989 1.849134
1: 1.869821 1.531483 1.849626
2: 1.869881 1.531900 1.849678
답변2
그리고 sed
, echo
그리고 tr
:
$ se () { echo -n "$1 "; sed -n 's/\s*r('"$2"').*|r| =\s\+//p' DEMLIR-GEO_OPT-1-distance-1.coordLog | tr '\n' ' '; echo; }
$ se 0 1,5; se 1 2,5; se 2 2,8
0 1.869679 1.869821 1.869881
1 1.530989 1.531483 1.531900
2 1.849134 1.849626 1.849678
# using a for-loop
cnt=0; for i in 1,5 2,5 2,8; do se $((cnt++)) $i; done
출력을 파일에 쓰려면 다음을 사용할 수 있습니다.
{ se 0 1,5; se 1 2,5; se 2 2,8; } > DEMLIR_task.txt
순서가 잘못된 경우 , 및 다음을 사용하여 이 코드 조각을 사용할 수 있습니다 sed
.paste
printf
$ se () { sed -n 's/\s*r('"$1"').*|r| =\s\+//p' DEMLIR-GEO_OPT-1-distance-1.coordLog; }
$ paste -d' ' <(printf '%s\n' 0 1 2) <(se 1,5) <(se 2,5) <(se 2,8)
0 1.869679 1.530989 1.849134
1 1.869821 1.531483 1.849626
2 1.869881 1.531900 1.849678
# using a for-loop and temp files, first column starts with 1 instead of 0
rm -f tmp.*; cnt=0; for i in 1,5 2,5 2,8; do se $i > tmp.$((cnt++)); done; paste -d ' ' tmp.* | cat -n
답변3
셸 옵션을 dist1: unbound variable
설정했기 때문에 오류 메시지가 나타납니다 . 그런 다음 변수를 설정하기 전에 사용할 nounset
수 있습니다 .dist1
/REQUESTED STRUCTURE DATA/ { ++n; m = 0 }
$6 == "|r|" { r[n,++m] = $NF }
END {
for (j = 1; j <= m; ++j) {
$0 = j - 1
for (i = 1; i <= n; ++i)
$(i + 1) = r[i,j]
print
}
}
(예를 들어 출력을 awk ... >DEMLIR_task.txt
새 파일에 저장하기 위해 리디렉션하는 데 사용)
데이터는 여러 부분으로 나누어지며, 각 부분은 행으로 시작 REQUESTED STRUCTURE DATA
하고 많은 레코드를 포함합니다. 해당 레코드는 |r|
6번째 필드의 문자열을 검색하여 찾을 수 있습니다.
위 awk
프로그램은 각 행 앞에 카운터가 있는 열 섹션에 있는 각 레코드의 마지막 필드에서 수집된 숫자를 출력합니다. 각 부분( m
코드의)에는 임의의 수의 레코드가 있을 수 있고 입력 데이터( n
코드의)에는 임의의 수의 부분이 있을 수 있다고 가정합니다 .
시험:
$ awk -f script.awk file
0 1.869679 1.869821 1.869881
1 1.530989 1.531483 1.531900
2 1.849134 1.849626 1.849678