안녕하세요, 파일 중간에 다음 줄이 있는데 "energy=" 뒤에 있는 값을 가져와야 합니다. 줄 번호는 "lineNumber"라는 변수에 저장됩니다. 파일에 구조는 동일하지만 값이 다른 다른 줄이 있습니다. 나는 "lineNumber"에 정의된 라인의 에너지 값만 원합니다. 도움을 주셔서 감사합니다. 감사합니다!
Properties=species:S:1:pos:R:3:velocities:R:3:forces:R:3:local_energy:R:1:fix_atoms:S:3 Lattice="42.0000000000 0.0000000000 0.0000000000 0.0000000000 46.0000000000 0.0000000000 0.0000000000 0.0000000000 50.0000000000" temperature=327.11679001 pressure=14.24003276 time_step=5.0000 time=5000.0000 energy=-18.022194 virial="0.46990039 0.48760331 -0.77576961 0.48760331 0.78141847 0.59471844 -0.77576961 0.59471844 0.64787347" stress="-0.00000486 -0.00000505 0.00000803 -0.00000505 -0.00000809 -0.00000616 0.00000803 -0.00000616 -0.00000671" volume=96600.000000 step=1000
답변1
Linux 기반 시스템을 사용하고 있으므로 GNU를 사용하고 있는 것이 거의 확실합니다.grep
grep -oP 'energy=\K[^\s]+'
예를 들어
echo 'Properties=species:S:1:pos:R:3:velocities:R:3:forces:R:3:local_energy:R:1:fix_atoms:S:3 Lattice="…" temperature=327.11679001 … time=5000.0000 energy=-18.022194 virial="0.46990039 …" stress="…" volume=96600.000000 step=1000' |
grep -oP 'energy=\K[^\s]+'
산출
-18.022194
당신은 다음과 같은 것을 사용할 수 있습니다sed
lineNumber=123
sed -n "${lineNumber}{p;q}" file
이것들을 종합하면,
sed -n "${lineNumber}{p;q}" file | grep -oP 'energy=\K[^\s]+'
다음과 같은 것을 사용할 수도 있습니다 perl
.
perl -e '
$lineNumber = shift; # Arg 1 is line number
$fieldName = shift; # Arg 2 is field name
while (defined($line = <>)) { # Read lines from file or stdin
next unless $. == $lineNumber; # Skip until required line
chomp $line; # Discard newline
%a = # Create key/value array. Read the next lines upwards
map { split(/=/, $_, 2) } # 3. Split into {key,value} tuples
grep { /=/ } # 2. Only interested in assignments
split(/(\w+=(".*?"|[^"].*?)\s+)/, $line); # 1. Split line into « key=value » and « key="several values" » fields
print $a{$fieldName}, "\n"; # Print chosen field value
exit 0
}
' "$lineNumber" 'energy' file
답변2
awk -v lineNumber="$lineNumber" -v FS="energy=" 'NR == lineNumber {print $2}' FILE | awk '{print $1}'
답변3
현재 요구 사항에 비해 약간 과잉일 수 있지만 레이블-값 매핑 배열을 만들 수 있습니다(아래 배열에 저장됨 f[]
).
$ awk -v FPAT='[^=[:space:]]+=([^[:space:]]+|"[^"]*")' -v n="$lineNumber" '
NR == n {
delete f
for (i=1; i<=NF; i++) {
f[gensub(/=.*/,"",1,$i)] = gensub(/[^=]+=/,"",1,$i)
}
print f["energy"]
}
' file
-18.022194
f[]
그런 다음 레이블(이름)을 사용하여 색인을 생성하여 값 또는 값 조합에 대해 원하는 작업을 수행할 수 있습니다. 예를 들어 다음과 같이 작성할 수 있습니다.
awk -v FPAT='[^=[:space:]]+=([^[:space:]]+|"[^"]*")' '
{
delete f
for (i=1; i<=NF; i++) {
f[gensub(/=.*/,"",1,$i)] = gensub(/[^=]+=/,"",1,$i)
}
}
(f["time"] < 6) && (f["volume"] > 8) {
print f["temperature"], f["energy"], f["step"] / f["time_step"]
}
' file
327.11679001 -18.022194 200
또는 비교/계산/인쇄해야 할 다른 모든 것.
위의 내용은 GNU awk를 사용하여 FPAT
sum 을 처리합니다 . 코드만 조금 더 추가하면 gensub()
지원되는 POSIX awk를 사용하여 대부분(모두는 아니지만)과 동일한 작업을 수행할 수 있습니다 .delete array
$ awk -v n="$lineNumber" '
NR == n {
delete f
rec = $0
while ( match(rec,/[^=[:space:]]+=([^[:space:]]+|"[^"]*")/) ) {
tag = val = substr(rec,RSTART,RLENGTH)
sub(/=.*/,"",tag)
sub(/[^=]+=/,"",val)
f[tag] = val
rec = substr(rec,RSTART+RLENGTH)
}
print f["energy"]
}
' file
-18.022194
awk가 불만을 표시하면 해당 줄을 어떤 awk에서도 작동하는 delete f
줄로 변경하세요 .split("",f)
답변4
사용행복하다(이전 Perl_6)
~$ raku -ne 'put ++$ => $/ if ++$ == 1 && m/ \s energy\= <( <+ :N + [\-+.]>+ )> \s /;' file
또는:
~$ raku -ne 'put ++$ => $0 if ++$ == 1 && m/ \s energy\= ( <+ :N + [\-+.]>+ ) \s /;' file
또는:
~$ raku -ne 'put ++$ => $<val> if ++$ == 1 && m/ \s energy\= $<val>=<+ :N + [\-+.]>+ \s /;' file
위의 Raku 코드는 -ne
자동 인쇄가 아닌 라인별 플래그를 사용합니다(코드는 입력 파일에서 라인별로 실행됩니다). 오른쪽에서 왼쪽으로 읽으면서 m/.../
다음 필수 값과 일치하는 항목을 찾습니다 energy=
. 이 일치 항목은 유니코드 숫자와 문자 , , 가 한 번 이상 나타나는 <+ :N + [\-+.]>+
복합 문자 클래스 인 Raku Regex 방언으로 작성되었습니다 ( 이 구조에서 백슬래시 이스케이프가 필요한 몇 안 되는 문자 중 하나). 이 문자 클래스를 작성할 수 있지만 유니코드 이외의 숫자와의 일치는 손실됩니다 .:N
-
+
.
-
<+[0..9\-+.]>+
0..9
++$
Raku에서 줄 번호를 계산하는 가장 간단한 방법은 1부터 시작하는 자동 증가 카운터를 실행하는 것입니다 . 이를 하나로 합치면(이제 왼쪽에서 오른쪽으로 읽음) 첫 번째 예제 코드는 다음과 같습니다."줄 번호가 수치적으로 1과 같고 줄 번호 put
뒤에 ++$
내장 $/
일치 변수가 오면 필요한 일치 항목이 발견되고 캡처 태그를 제외한 모든 항목이 제거됩니다."if ++$ == 1
&&
<( ... )>
. 부울은 &&
사용되기 때문에 단락됩니다. ( ++$ =>
반환하려는 것이 값뿐이라면 출력에서 해당 값을 제거하십시오.)
샘플 입력(OP의 데이터는 3회 사용됨):
Properties=species:S:1:pos:R:3:velocities:R:3:forces:R:3:local_energy:R:1:fix_atoms:S:3 Lattice="42.0000000000 0.0000000000 0.0000000000 0.0000000000 46.0000000000 0.0000000000 0.0000000000 0.0000000000 50.0000000000" temperature=327.11679001 pressure=14.24003276 time_step=5.0000 time=5000.0000 energy=-18.022194 virial="0.46990039 0.48760331 -0.77576961 0.48760331 0.78141847 0.59471844 -0.77576961 0.59471844 0.64787347" stress="-0.00000486 -0.00000505 0.00000803 -0.00000505 -0.00000809 -0.00000616 0.00000803 -0.00000616 -0.00000671" volume=96600.000000 step=1000
Properties=species:S:1:pos:R:3:velocities:R:3:forces:R:3:local_energy:R:1:fix_atoms:S:3 Lattice="42.0000000000 0.0000000000 0.0000000000 0.0000000000 46.0000000000 0.0000000000 0.0000000000 0.0000000000 50.0000000000" temperature=327.11679001 pressure=14.24003276 time_step=5.0000 time=5000.0000 energy=-18.022194 virial="0.46990039 0.48760331 -0.77576961 0.48760331 0.78141847 0.59471844 -0.77576961 0.59471844 0.64787347" stress="-0.00000486 -0.00000505 0.00000803 -0.00000505 -0.00000809 -0.00000616 0.00000803 -0.00000616 -0.00000671" volume=96600.000000 step=1000
Properties=species:S:1:pos:R:3:velocities:R:3:forces:R:3:local_energy:R:1:fix_atoms:S:3 Lattice="42.0000000000 0.0000000000 0.0000000000 0.0000000000 46.0000000000 0.0000000000 0.0000000000 0.0000000000 50.0000000000" temperature=327.11679001 pressure=14.24003276 time_step=5.0000 time=5000.0000 energy=-18.022194 virial="0.46990039 0.48760331 -0.77576961 0.48760331 0.78141847 0.59471844 -0.77576961 0.59471844 0.64787347" stress="-0.00000486 -0.00000505 0.00000803 -0.00000505 -0.00000809 -0.00000616 0.00000803 -0.00000616 -0.00000671" volume=96600.000000 step=1000
출력 예(탭으로 구분된 반환):
1 -18.022194
lineNumber
마지막으로, 한 줄에 하드코딩하는 대신 명령줄에서 입력하고 싶다면 env
Raku는 내부적으로 환경 변수를 동적 해시 변수로 사용할 수 있습니다 %*ENV
. 따라서 다음을 수행할 수 있습니다(첫 번째 문자 env
는 선택 사항임).
~$ env lineNumber="1" perl6 -ne 'put $0 if ++$ == %*ENV<lineNumber> && m/ \s energy\= ( <+[0..9\-+.]>+ ) \s /;' file
-18.022194