간단한 디스크 사용 셸 스크립트(대시)를 만들려고 하는데 AWK 구문에 익숙하지 않기 때문에 문자열을 구문 분석하는 방법을 잘 모르겠습니다.
저는 다음 명령을 사용합니다. df -P -BG /
예를 들어 다음과 같은 출력이 표시됩니다.
Filesystem xxxxxxxxxx-blocks Used Available Capacity Mounted on
/dev/mapper/xxx_crypt 500G 200G 100G xx% /
"사용됨"(궁극적으로는 "사용 가능") 아래의 열을 추출하고 싶지만 어떻게 해야 할지 잘 모르겠습니다. AWK에는 다음과 같은 검색 명령이 있다는 것을 알고 있습니다.awk '/Used/ {print}'
하지만 그 아래 행을 얻는 방법을 모르겠습니다. 어떤 팁이 있나요? 예를 들어 df -P -BG / | awk '...'
쉘 변수에 저장하기 때문에 한 줄에서 파이프로 작동하는 것이 중요 하지만 여러 줄의 AWK를 사용할 수 있으므로 꼭 필요하다고 생각하지 않습니다.
답변1
구현에서 지원하는 경우 구문 분석 대신 df
사용할 수 있습니다 . 내 아치 리눅스 --output
에서 :man df
--output[=FIELD_LIST]
use the output format defined by FIELD_LIST, or print all fields if
FIELD_LIST is omitted.
[...]
FIELD_LIST is a comma-separated list of columns to be included.
Valid field names are: 'source', 'fstype', 'itotal', 'iused',
'iavail', 'ipcent', 'size', 'used', 'avail', 'pcent',
'file' and 'target' (see info page).
따라서 귀하의 경우에는 다음을 수행하십시오.
$ df -BG --output="used" /
Used
200G
정말로 구문 분석이 필요한 경우 패턴 일치에 전혀 신경 쓰지 않을 것입니다. 입력을 제어하면 변경되지 않으므로 세 번째 필드(내 시스템의 출력)만 인쇄할 수 있습니다.
$ df -P -BG / | awk '{print $3}'
Used
44G
필드 순서가 변경되더라도 작동하도록 해야 하는 경우 문자열이 포함된 필드를 찾아야 하는 경우 Used
다음과 같이 복잡한 작업을 수행할 수 있습니다.
$ df -P -BG / |
awk '{ if(NR==1){for(i=1; i<=NF; i++){ if($i ~ /Used/){want=i}}} print $want}'
Used
44G
답변2
FPAT, FIELDIDTHS, \s, \S 및 gensub()와 함께 GNU awk를 사용하십시오.
$ cat tst.awk
BEGIN { FPAT="\\S+|\\s+"; OFS="\t" }
NR == 1 {
sub(/Mounted on/,"Mounted_on")
for ( i=1; i<=NF; i+=2 ) {
tags[++numTags] = $i
wids = wids " " length($i $(i+1))
}
FIELDWIDTHS = wids
$0 = $0
}
{
for ( i=1; i<=NF; i++ ) {
f[tags[i]] = gensub(/^\s+|\s+$/,"","g",$i)
}
print f["Filesystem"], f["Available"], f["Used"]
}
$ cat file | awk -f tst.awk | column -s $'\t' -t
Filesystem Available Used
/dev/mapper/xxx_crypt 100G 200G
나에게 없는 것으로 교체하세요 cat file
. 정렬을 위해 열을 df -P -BG /
파이프로 연결했는데 column
이는 필요하지 않습니다.
이렇게 하면 이름으로 인쇄하고, 비교하고, 재정렬하고, 원하는 열의 값에 대해 산술 연산을 수행하는 등의 작업을 수행할 수 있습니다. 코드에서 수정해야 했던 유일한 것은 공백을 밑줄로 변경하여 "설치"하는 것이었습니다.
다음은 모든 awk에서 작동하는 버전입니다.
$ cat tst.awk
BEGIN { OFS="\t" }
NR == 1 {
sub(/Mounted on/,"Mounted_on")
while ( match(substr($0,totWid+1),/[^ \t]+[ \t]*/) ) {
tag = substr($0,totWid+1,RLENGTH)
sub(/[ \t]+$/,"",tag)
tags[++numTags] = tag
begs[numTags] = totWid + 1
wids[numTags] = RLENGTH
totWid += RLENGTH
}
}
{
for ( i=1; i<=numTags; i++ ) {
val = substr($0,begs[i],wids[i])
gsub(/^[ \t]+|[ \t]+$/,"",val)
f[tags[i]] = val
}
print f["Filesystem"], f["Available"], f["Used"]
}
$ awk -f tst.awk file | column -s $'\t' -t
Filesystem Available Used
/dev/mapper/xxx_crypt 100G 200G
답변3
사용행복하다(이전 Perl_6)
~$ raku -e 'my $target = "Used";
my @table = lines.map: *.split(/ \h+ /).List;
my $col = @table.head.grep(/ $target /, :k).cache;
.put for @table.map: *.[ $col.flat ];' file
위 내용은 Perl 계열의 프로그래밍 언어인 Raku로 작성된 답변입니다. 즉, $
-sigiled 스칼라가 선언되고 "Used"라는 문자열이 할당됩니다. 그런 다음 lines
읽으면 각 ped가 수평 공백 map
으로 들어갑니다 . 일반적으로 이러한 반환은 Raku에서 a라는 경량 데이터 구조에 저장되지만 여기서는 데이터를 배열 에 저장하도록 강제합니다.split
\h
Seq
List
@table
이제 올바른 열을 살펴보세요. @table.head
테이블의 원래 헤더 행(즉, 행)을 가져옵니다 . grep
일치 항목을 찾기 위해 이러한 요소를 살펴본 다음 $target
열 :k
인덱스 번호인 키를 가져와서 에 저장합니다 $col
. 마지막으로 필요한 열만 반환하여 put
데이터를 출력합니다 .@a.table
$col
입력 예:
Filesystem xxxxxxxxxx-blocks Used Available Capacity Mounted on
/dev/mapper/xxx_crypt 500G 200G 100G xx% /
예제 출력:
Used
200G
OP는 쉘 변수를 허용하는 스크립트에 대한 희망을 표현했습니다. Raku에는 %*ENV
쉘 변수에 액세스하는 데 사용할 수 있는 특수 연관 배열이 있습니다 . 따라서 다음은 colName
환경(즉, 셸)에서 셸 변수를 가져옵니다.
~$ env colName="Used" raku -e 'my $target = %*ENV<colName>; \
my @table = lines.map: *.split(/ \h+ /).List; \
my $col = @table.head.grep(/$target/, :k).cache; \
.put for @table.map: *.[ $col.flat ];' file
Used
200G
다음과 같이 약간의 조정을 통해 유사하게 두 개의 열 등을 반환할 수 있습니다.
~$ env colNames="Used Available" raku -e ' \
my @target = %*ENV<colNames>.split(/ \h+ /).List; \
my @table = lines.map: *.split(/ \h+ /).List; \
my @col = @table.head.grep(/@target/, :k); \
.put for @table.map: *.[ @col.flat ];' file
Used Available
200G 100G