다음 형식의 파일이 있습니다.
INTEGER INTEGER TEXT
텍스트는 유니코드이며 공백을 포함할 수 있습니다.
printf를 사용하여 파일의 첫 번째 INTEGER 및 TEXT를 특정 형식으로 인쇄하기 위해 awk를 사용하려고 합니다.
문제: 일부 줄의 TEXT에 공백이 있으므로 $3에는 완전한 TEXT가 없으므로 더 많은 필드에서 줄이 손상됩니다.
예:
12 42956 Cinema - 3D/Multiplex
7 12560 Status Update
5 184 Movie
내 접근 방식은 다음과 같습니다.
awk '{ c=$3; for(i=4; i< NF;++i){c=c" "$i}; printf "<tag>%d</tag>\n<tag>%s</tag>\n", $1,c}';
하지만 더 좋은 방법이 있을 것 같아요
답변1
awk
데이터가 명확하게 지정된 레코드에서 나온 경우 유용합니다. 이 데이터는 사용할 수 없습니다. 그러나 데이터는 " integer stuff the_rest
" 형식이며 " integer
" 또는 " " stuff
에 공백이 없습니다 . 이것이 바로 read
유틸리티가 읽고 싶어하는 것입니다. 읽도록 지정한 변수만큼 공백으로 구분된 단어를 읽은 다음 줄의 "나머지"를 마지막 변수에 넣습니다.
bash-4.4$ while read -r integer stuff the_rest; do printf '%d\t"%s"\n' "$integer" "$the_rest"; done <data
12 "Cinema - 3D/Multiplex"
7 "Status Update"
5 "Movie"
모든 후행 공백을 자동으로 제거합니다.
답변2
스키마를 기반으로 필드를 추출하는 것이 perl
다음보다 나은 경우가 많습니다 awk
.
perl -lne '
if (/^\s*(\d+)\s*\S+\s*(.*?)\s*$/) {
print "<tag>$1</tag><tag>$2</tag>"
}'
귀하의 의견은 다음을 제공합니다.
<tag>12</tag><tag>Cinema - 3D/Multiplex</tag>
<tag>7</tag><tag>Status Update</tag>
<tag>5</tag><tag>Movie</tag>
이는 필요한 경우 적절한 HTML 인코딩과 같은 고급 작업을 수행할 수 있음을 의미합니다. 예를 들면 다음과 같습니다.
perl -Mopen=locale -MHTML::Entities -lne '
if (/^\s*(\d+)\s*\S+\s*(.*?)\s*$/) {
print map {"<tag>" . encode_entities($_) . "</tag>"} $1, $2
}'
또는 XML 인코딩:
perl -Mopen=locale -MXML::LibXML -lne '
if (/^\s*(\d+)\s*\S+\s*(.*?)\s*$/) {
print map {
my $e = XML::LibXML::Element->new("tag");
$e->appendText($_);
$e->toString} $1, $2
}'
답변3
$2(어쨌든 사용하지 않음)를 사용되지 않은 문자(문자열에 존재하지 않는 문자)로 바꿉니다. 그 후에는 다음을 수행하세요.
awk '{$2="+";print}' input-file.txt | awk -F "+" '{printf "<tag>%d</tag>\n<tag>%s</tag>\n",$1,$2}'
위에서는 더하기 기호 "+"를 구분 기호로 사용했습니다.
가장 우아한 해결책은 아니지만 간단합니다.
답변4
이것이 큰 파일이 아니고 텍스트가 항상 끝에 있으므로 대안으로 다음과 같은 고전적인 bash 접근 방식을 사용하는 것을 고려할 수 있습니다.
while IFS=' ' read -r int1 int2 text;do
#do your stuff
done <file
while - read의 경우와 마찬가지로 read 명령의 마지막 var $text는 나머지 모든 필드를 하나의 필드로 가져옵니다.
시험:
$ IFS=' ' read -r int1 int2 text <<<"10 5 some text here"
$ echo "$text"
some text here
읽는 동안 Bash는 대용량 데이터 파일에서 상당히 느릴 수 있지만 귀하의 경우에는 시도해 볼 수 있습니다.