다음과 같은 .txt 파일이 있습니다.
table columns are:
subject code
date of birth
favorite activities
height (m)
weight (lbs)
test score + standard deviation
color blind
number of siblings
average score
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
table columns are:
... (repeat)
나는 이것을 다음과 같이 바꾸고 싶습니다 :
subject_8293748/label/NMA.label
subject code 56
date of birth 6.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
subject..(repeat)
n번째 행마다 이 작업을 어떻게 수행할 수 있나요? 매우 감사합니다!
답변1
귀하의 데이터는 얼마나 정적인가요? 이게 부정행위인가요?
awk '/^[0-9]/ {print $10 "\nsubject code\t\t\t" $1 "\ndate of birth\t\t\t" $2"\nfavorite activities\t\t" $3 "\nheight (m)\t\t\t" $4 "\nweight (lbs)\t\t\t" $5 "\ntest score + standard deviation\t" $6 "\ncolor blind\t\t\t" $7 "\nnumber of siblings\t\t" $8 "\naverage score\t\t\t" $9}' data.txt
답변2
OP에 표시된 9개 속성 이름뿐만 아니라 모든 속성 이름과 속성 이름 수를 허용하도록 입력 파일 처리를 자동화하고 일반화할 수 있습니다.
"subject code"
"date of birth"
"favorite activities"
"height (m)"
"weight (lbs)"
"test score + standard deviation"
"color blind"
"number of siblings"
"average score"
awk를 사용하여 이를 수행하는 한 가지 방법은 다음과 같습니다.
awk -v i=0 -v nAtt=9 '
/table columns are:/ {i+=1;ii=nAtt*(i-1);next}
!/(^$|^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+)/ {ii+=1;a[ii]=$0}
/^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+/
{printf "\n%s\n", $(nAtt+1);
c=0;
for(ii-=nAtt;ii++<1+(nAtt-1)*i;) {c++;printf "%-34s%s\n",a[ii],$c}}
' file.txt
설명하다:
- 이 awk 한 줄 명령문은 세 부분으로 구성되며, 모두 와 같은 패턴 일치
/.../
또는 다음과 같은 안티매칭 으로 시작합니다.!/ .../
- 하지만 먼저 호출할 때 옵션이 있는 두 개의 외부 변수 를
awk
전달합니다-v
. 는 데이터 블록의 순위(즉, 입력 파일에 있는 속성 블록의 시퀀스 번호: )를 나타내는 것이 아니라 이 솔루션의 각 데이터 블록에 대해 동일해야 하는 속성의 수를 나타냅니다.i=0
nAtt=9
i
file.txt
nAtt
awk
첫 번째 패턴 일치: 패턴을 볼 때마다table columns are:
새로운 데이터 블록이 다음 레코드로 시작한다는 것을 알고 두 개의 카운터를 설정i
하고ii
다음 레코드로 점프합니다.- 두 번째 패턴 일치: 읽고 있는 레코드가 빈 줄도 일치할 수 있는 줄도 아닌 경우:
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
배열a
의 카운터를 증가시키고ii
도달할 때까지 속성 이름 문자열로 배열을 채우기 시작합니다. - 세 번째 패턴 일치: 레코드가
56 6.18 1307 5.73 167 0.564 2 3 1.7
임의 개수의 문자와 일치하는 경우(nAtt+1)
해당 레코드의 번째 필드를 인쇄한 다음nAtt
속성 이름과 값을 한 줄에 하나씩 인쇄하여 속성 이름이 왼쪽 정렬되고 길이가 초과하면 잘립니다. 34자.
이전에 암시했듯이:
- 이는 속성 블록당 속성 수(nAtt)와 블록마다 달라지는(또는 변경되지 않는) 속성 이름에 적용됩니다.
- 사소한 스크립트 수정만으로 블록당 다양한 속성을 갖는 것이 가능하고 쉽습니다.
외부 변수는 에 전달될 수 있습니다
awk
. 예를 들면 다음과 같습니다.awk -v i=$i -v nAtt=$nAtt '...'
답변3
이것은 한 가지 방법입니다
awk 'BEGIN {
a[1]="subject code"
a[2]="date of birth"
a[3]="favorite activities"
a[4]="height (m)"
a[5]="weight (lbs)"
a[6]="test score + standard deviation"
a[7]="color blind"
a[8]="number of siblings"
a[9]="average score"
} {
print $10
for(c=0;c++<9;) {
printf "%-34s%s\n",a[c],$c
}
}' file.txt
예제 실행
$ cat file.txt
56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
51 3.18 1307 5.73 167 0.564 2 3 1.7 subject_8293755/label/NMA.label
$ awk 'BEGIN {
a[1]="subject code"
a[2]="date of birth"
a[3]="favorite activities"
a[4]="height (m)"
a[5]="weight (lbs)"
a[6]="test score + standard deviation"
a[7]="color blind"
a[8]="number of siblings"
a[9]="average score"
} {
print $10
for(c=0;c++<9;) {
printf "%-34s%s\n",a[c],$c
}
}' file.txt
subject_8293748/label/NMA.label
subject code 56
date of birth 6.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
subject_8293755/label/NMA.label
subject code 51
date of birth 3.18
favorite activities 1307
height (m) 5.73
weight (lbs) 167
test score + standard deviation 0.564
color blind 2
number of siblings 3
average score 1.7
$