내 ASCII 파일은 다음과 같습니다.
a
1 2 3
1223
b
1 2 3 5
3344
1223
c
1 2 34
a
4 5
c
123
a, b, c 아래의 행을 각각 수집하는 방법은 무엇입니까?
묻다:다음 줄을 얻으려면 어떻게 해야 합니까?
a
1 2 3
1223
4 5
답변1
awk '/^[a-z]$/ { f = $1=="a" ; if (!c++) print ; next }; f'
답변2
아, awk
지금까지 본 다른 솔루션과 달리 하나의 데이터 전달만 사용하므로 작업이 훨씬 쉬워집니다.
/^[a-z]/{key=$0;}
/^[0-9]/{if (key in res){ res[key]=res[key] "\n" $0;} else {res[key]=$0;}}
END {for(key in res){
print key;
print res[key];
}}
sed
+프릴만 원한다면 다음과 같이 작동하는 것 같습니다.
cat data.txt | sed -e '/^a/,/^[b-z]/!d' | sed -e '2,${ /^[a-z]/d }'
(예, 이것은고양이의 쓸모없는 사용 교육학적 이유 때문에, 즉 파일이 파이프라인 중간 어딘가에 있으면 혼란스러워집니다. )
첫 번째는 sed
문자(포함)로 시작하는 줄로 시작하고 끝나는 모든 범위를 고려합니다. 범위()를 무효화한 다음 일치하는 모든 항목을 제거하므로 다음과 같이 남습니다.a
b-z
!
a
1 2 3
1223
b
a
4 5
c
두 번째는 sed
헤더를 유지하기 위해 라인 2부터 파일 끝까지의 범위만 살펴보고 a
거기에서 문자로 시작하는 모든 라인을 제거 a-z
하고 숫자 라인만 남깁니다.
a
1 2 3
1223
4 5
모든 제목의 목록을 얻으려면 시도해 볼 것입니다 grep '^[a-z]' | sort -u
. 따라서 전체 짐승은 다음과 같습니다.
for key in $(grep '^[a-z]' data.txt | sort -u ); do
cat data.txt | sed -e "/^$key/,/^[b-z]/\!d" | sed -e '2,${ /^[a-z]/d }' ;
done
답변3
awk '
/^[a-z]$/{
i=$0
next
}
{
A[i]=A[i] "\n" $0
}
END{
for (j in A)
print j A[j]
}'
보시다시피 이는 다음의 단순화된 변형입니다.@Ulrich Schwarz 스크립트: 소문자 하나만 포함된 줄의 경우 이 문자를 색인으로 사용 i
하고 새 줄 루프를 시작합니다. 다음으로, 스크립트의 이전 부분에서 ewline 구분 기호를 사용하여 결정된 인덱스를 A
기반으로 나머지 모든 줄(이전에 조작되었기 때문에 "단지 1개의 소문자"가 아님)을 연관 배열에 배치합니다 . 스크립트가 모든 행(도달)을 전달하면 배열이 인덱스로 인쇄됩니다.i
\n
END
A
i
답변4
awk
두 번째 인쇄를 방지하는 방법은 다음 과 같습니다 a
.
awk '$1 == "a" { if (!head) print; n=head=1; next } $1 !~ /^[0-9]/ { n=0 } n' ascii_file
이러한 결과를 얻으려면 다음 "a"
으로 바꾸십시오 ."b"
산출:
a
1 2 3
1223
4 5
루프를 원하면 다음과 같이 할 수 있습니다.
for letter in a b c; do
echo
awk -v letter="$letter" '$1 == letter { if (!head) print; n=head=1; next } $1 !~ /^[0-9]/ { n=0 } n' /tmp/a
done
다음과 같이 출력됩니다.
a
1 2 3
1223
4 5
b
1 2 3 5
3344
1223
c
1 2 34
123
(이 echo
줄에 주목하세요. 각 쿼리에 대한 조회수를 구분합니다. 이 답변을 작성하여 알파벳순으로 쿼리할 수 있도록 했습니다. 이것이 바로 질문에 대한 이해입니다.)