항목(N=1000)에 대한 정보를 항목당 구분된 텍스트 파일(각 항목당 하나의 텍스트 파일)로 내 컴퓨터에 저장합니다. 기록되는 정보 형식은 다음과 같습니다.
============
NAME: Matty Nigan
Age: 65
Sex: M
Weight: XX
TIME: 12:31:25
Home address: XXXXX
Phone number: XXX XXX XXXX
============
다음과 같이 이러한 항목(N=1000)에서 모든 데이터를 수집하고 구성하고 싶습니다.
NAME AGE SEX Weight HOME Phone
===========
Matty Nigan 65 M XX XX XX
..........
..........
..........
..........
나는 이 코드를 시도했다:
#!/bin/bash
source=path to the folder where the entries files are.
for i in $(cat file.txt); do # file.txt is including all the delimited text files names
awk '
/Name:/ {name=$2}
/Age:/ {age=$2 }
/Sex:/ {sex=$2}
/Home: / {home=$3}
/Phone:/ {phone=$3}
BEGIN { FS=":"; print "name\t\tage\t\tsex\t\thome\t\tphone:\n---------"; }
{print $2,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}END{ print "---------\nFile Complete" }'
' ${source}/${i}| sh > outdata.csv
done
불행히도 이것은 작동하지 않습니다! 내가 뭘 잘못했는지 모르겠습니다. 어떤 도움이라도 대단히 감사하겠습니다.
답변1
awk '
BEGIN {
fmt="%-15s%-10s%-10s%-10s%-10s%-10s\n"
printf fmt,"Name","Age","Sex","Weight","Home","Phone"
print "---------"
}
{
v=$0
sub(/[^:]*: /, "", v)
a[$1]=v
}
/Phone/ {
printf fmt,a["NAME:"],a["Age:"],a["Sex:"],a["Weight:"],a["Home"],a["Phone"]
delete a
}
END{
print "---------\nFile Complete"
}' file*
열 사이에 이중 탭을 사용하는 것은 문제가 있습니다. 예를 들어 긴 이름과 짧은 이름이 모두 있는 경우 열이 뒤섞여 정확히 잘못된 위치에 표시될 수 있습니다. 위에서는 주어진 너비로 열의 형식을 지정했습니다. 최상의 결과를 얻으려면 너비를 조정해야 할 수도 있습니다.
이로 인해 FS=":"
문제가 발생할 수도 있습니다. 필드에는 계산에 혼란을 주는 콜론이 포함될 수 있습니다. 이는 다음과 같이 첫 번째 콜론의 정보를 삭제하여 방지할 수 있습니다. 다음 명령문은 모든 파일 정보를 배열로 캡처합니다 a
.
v=$0
sub(/[^:]*: /, "", v)
a[$1]=v
첫 번째 필드가 키입니다. 첫 번째 콜론 공백 이후의 모든 내용은 값입니다.
단일 awk 명령으로 여러 파일을 처리할 수 있습니다. 위에서 언급한 대로 file*
glob과 일치하는 모든 파일이 처리됩니다. 데이터 파일과 일치하는 모든 glob으로 바꾸십시오.
한 번에 한 사람씩 처리하십시오. 이는 코드가 많은 메모리를 필요로 하지 않으므로 대규모 데이터 세트에 적합하다는 것을 의미합니다.
샘플 출력
$ bash script.sh
Name Age Sex Weight Home Phone
---------
Matty Nigan 65 M XX XXXXX XXX XXX XXXX
---------
File Complete
답변2
다음과 같이 구성된 awk를 사용해 보세요. 세부 정보가 포함된 배열을 만들고 마지막에 배치를 인쇄합니다.
awk -F: '
/^NAME/{name[c]=$2}
/^Age:/{age[c]=$2}
/^Sex:/{sex[c]=$2}
/^Weight:/{weight[c]=$2}
/^Home address:/{home[c]=$2}
/^Phone number:/{phone[c]=$2;c++}
END {
print "NAME AGE SEX Weight HOME Phone"
print "==========="
for(x in name) {
printf "%-10s %3d %s %s %s %s\n",
substr(name[x],2),
age[x],
sex[x],
weight[x],
home[x],
phone[x]
}
}'
답변3
또한 각 입력 레코드에 대해 "{print $2..."로 시작하는 문이 실행되는 것처럼 보입니다. /PHONE:/ 선택기 뒤에 인쇄 내용을 중괄호로 묶는 것이 좋습니다. 또한 이 작업을 수행하려면 BEGIN 섹션을 그대로 추가하는 대신 프로그램 헤드에 배치합니다.
이전 의견에서 지적했듯이 인쇄물에는 $2, $3, $4 등이 아닌 이름, 나이, 성별 등이 있어야 합니다.
/PHONE:/ {phone=$3}이(가) 문제를 일으킬 것 같아요. 샘플 데이터에 표시된 대로 전화번호의 세 자리 숫자 세트(공백으로 구분)는 awk에 $3 $4 $5로 나타납니다. 따라서 전화번호 전체를 수집하려면 /PHONE:/{phone = $3 "-" $4 "-" $5} 가 더 적합할 것입니다.