다음 줄을 포함하는 텍스트 파일이 있다고 가정합니다.
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
abcd/efgh/a.jar
{
cdef/ghij/b.class
}
이제 첫 번째 경우 abcd/efgh/a.jar에는 중괄호 안에 abcd/efgh/a.class, cdef/ghij/b.class 및 klmn/opqr/c.class가 있습니다. 1개의 텍스트 블록으로 생각하세요. 이제 다음 abcd/efgh/a.jar에는 다시 중괄호 안에 cdef/ghij/b.class가 있습니다. 이 텍스트 섹션/블록을 제거하고 싶습니다. 따라서 최종 출력은 다음과 같아야 합니다.
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
어떤 도움이라도 대단히 감사하겠습니다 :)
답변1
사용
for i in `awk '/}/ {if (NR!=1) print "";next} \
{printf "%s ",$0,"}"}END{print ""}' yt.txt \
|awk '{print $1}'|sort|uniq \
`; \
do \
awk '/}/ {if (NR!=1) print "";next} \
{printf "%s ",$0,"}"}END{printf ""} \
' yt.txt \
|grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq \
|awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}' \
;done \
아래 한 줄의 동일한 명령(복사 목적)
for i in `awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{print ""}' yt.txt|awk '{print $1}'|sort|uniq` ; do awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{printf ""}' yt.txt|grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq|awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}' ;done
설명하다:
이 섹션은 블록의 고유 제목( , ) for
을 반환 하고 이를 블록에 전달합니다. 이 섹션에는 먼저 중복 항목을 포함하여 각 제목에 대한 모든 행이 표시됩니다 . 그런 다음 헤더를 제외하고 해당 헤더 블록 아래에 남아 있는 모든 행을 병합한 다음 첫 번째 행에 헤더를 추가합니다. 그리고 마지막에 하드코딩했습니다.abcd/efgh/a.jar
lkmn/opqr/b.zip
do
do
grep
}
예
bash-4.2$ cat yt.txt
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
abcd/efgh/a.jar
{
cdef/ghij/b.class
d.class
}
bash-4.2$ for i in `awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"} \
> END{print ""}' yt.txt |awk '{print $1}'|sort|uniq` \
> ; do awk '/}/ {if (NR!=1) print "";next} {printf "%s ",$0,"}"}END{printf ""}' yt.txt \
> |grep "$i"|sed 's/ /\n/g'|grep -v "$i"|sort|uniq \
> |awk -v var="$i" ' NR==1 {printf var} {print $0} END {print "}"}'\
> ;done
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
d.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
답변2
for
awk
and sort
및 and 가 포함된 uniq
루프를 사용하는 솔루션을 본 후 6개 도구 대신 하나의 도구를 사용하여 솔루션을 시도했습니다.grep
sed
sed ':a
N;$!ba
y/\n_/_\n/;s/^/_/
:b
s/\(_[^_]*_{\)\([^}]*\)\(_[^_}]*\)\(_[^}]*\)\(_}.*\)\1\([^}]*\)\3_/\1\2\3\4\5\1\6_/;tb
:c
s/\(_[^_]*_{\)\([^}]*\)_}\(.*\)\1\([^}]*\)_}/\1\2\4_}\3/;tc
s/^_//
y/\n_/_\n/' yourfile
그 일을 할 수는 있지만 정규식 작성이 읽는 것보다 쉽다는 점을 인정해야 합니다... (-;
답변3
perl -alF'/\n[}{]\n/' -0777ne '
for ( 0 .. $#F/2 ) {
my $i = 2*$_;
my($k,$v) = @F[$i,$i+1];
if ( exists $h{$k} ) {
$h{$k} .= join $\, grep { ! exists $seen{$k,$_} } split $\, $v;
} else {
push @k, $k;
$seen{$k,$_}++ for split $\, $h{$k} = $v;
}
}
print "$_\n{\n$h{$_}\n}" for @k;
' yourfile
결과
abcd/efgh/a.jar
{
abcd/efgh/a.class
cdef/ghij/b.class
klmn/opqr/c.class
}
lkmn/opqr/b.zip
{
abcd/efgh/a.class
cdef/ghij/b.class
}
피복재
입력 파일은 다이제스트된 다음 옵션에 언급된 필드 구분 기호에 따라 필드로 분할됩니다 -F
. 우리는 배열에서 짝수의 요소를 얻게 될 것입니다 @F
. 그런 다음 짝수는 %h
대응하는 동안 해시 키 역할을 합니다. 값은 다음 홀수부터 가져옵니다.
%h
해시는 레코드 구분 기호($\ = \n)에서 홀수 요소를 분할하여 채워집니다. 동시에 @k
해시 요소를 발견된 순서대로 검색할 수 있도록 키를 배열에 넣습니다.
그동안 아직 본 적이 없는 이상한 요소들만 사용하고 있습니다.