![텍스트 파일에서 csv로 데이터 추출](https://linux55.com/image/92005/%ED%85%8D%EC%8A%A4%ED%8A%B8%20%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C%20csv%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EC%B6%94%EC%B6%9C.png)
일관된 형식의 일련의 텍스트 파일이 있습니다. 예를 들면 다음과 같습니다.
FirstName: Mary
LastName: Smith
Address: 123 Anywhere St
City: Nowhere
State: TX
Zip: 77777
이 파일에서 몇 줄을 추출하여 다음 형식의 csv 파일로 출력해야 합니다.
<filename>,<FirstName>,<City>,<Zip>
간단한 grep을 사용하여 원하는 필드를 얻을 수 있지만 필요한 방식으로 출력을 얻는 방법을 모르겠습니다.
답변1
파일당 하나의 레코드만 있는 경우 이는 간단한 읽기 루프입니다.
#!/bin/bash
read_data()
{
local first last addr city state zip
file=$1
while read -r header data
do
case $header in
FirstName:) first=$data ;;
LastName:) last=$data ;;
Address:) addr=$data ;;
City:) city=$data ;;
State:) state=$data ;;
Zip:) zip=$data ;;
*) echo Ignoring bad line $header $data >&2
esac
done < $file
echo "$file,$first,$last,$addr,$city,$state,$zip"
}
for file in *srcfiles*
do
read_data $file
done
이 read_data
함수는 각 행을 읽고 행을 "헤더"와 "데이터"로 분리합니다. 파일 끝에 도달하면 결과를 인쇄합니다.
루프를 통해 각 소스 파일에 대해 이 함수를 한 번씩 호출합니다 for
.
몇 가지 잠재적인 문제에 유의하세요. 데이터에 쉼표가 있으면 문제가 발생하므로 다음을 수행할 수 있습니다.
echo "\"$file\",\"$first\",\"$last\",\"$addr\",\"$city\",\"$state\",\"$zip\""
"..."
레이아웃 내에 포함된 모든 내용을 출력으로 사용합니다. 이로 인해 "
데이터에 내용이 있는 경우 CSV 형식이 잘못될 수도 있습니다.
echo
원하는 형식에 맞게 선을 조정하세요 .
답변2
귀하의 요구 사항에 맞는 빠르고 더러운 접근 방식입니다.
grep . *|perl -ne 'if(/FirstName: (.*)/){$f=$1}if(/City: (.*)/){$c=$1}if(/^(.*):Zip: (.*)/){print "$1,$f,$c,$2\n"}'
예:
grep . *
f1.txt:FirstName: Mary
f1.txt:LastName: Smith
f1.txt:Address: 123 Anywhere St
f1.txt:City: Nowhere
f1.txt:State: TX
f1.txt:Zip: 77777
f2.txt:FirstName: Joe
f2.txt:LastName: Bloggs
f2.txt:Address: 444 Anywhere St
f2.txt:City: Nowhere2
f2.txt:State: TXA
f2.txt:Zip: 77737
grep . *|perl -ne 'if(/FirstName: (.*)/){$f=$1}if(/City: (.*)/){$c=$1}if(/^(.*):Zip: (.*)/){print "$1,$f,$c,$2\n"}'
f1.txt,Mary,Nowhere,77777
f2.txt,Joe,Nowhere2,77737
답변3
파일당 레코드가 하나만 있고 GNU awk가 있는 경우 다음을 수행할 수 있습니다.
gawk -F': +' -vOFS=, '
BEGINFILE{delete rec}
{rec[$1] = $2}
ENDFILE{print FILENAME, rec["FirstName"], rec["City"], rec["Zip"]}
' file1.txt file2.txt ...