텍스트 필드가 있는 탭으로 구분된 데이터 파일이 있는데, 그 중 일부는 세미콜론으로 구분되어 반복되는 정보를 가지고 있습니다.
2000;2000
05/19/2016;05/19/2016
foo;foo
중복된 부분을 어떻게 sed
제거할 수 있나요? 세미콜론은 다른 필드에 자주 나타나므로 세미콜론 양쪽에 있는 문자열을 검색하고 탭 문자, 즉 \t$1;$1\t
( \t
탭을 의미)로 묶인 다음 $1
세미콜론과 중복이 없는 문자열 로 바꿔야 할 것 같습니다. 인스턴스 사이트. 다른 텍스트 구문 분석 명령을 사용할 수 있습니다.
답변1
파일에서 다음을 사용하십시오 tabbed.input
(공백 없음, 연속된 모든 공백은 탭임).
abc bd c 2000;2000 d 2;00;2;01
e 05/19/2016;05/19/2016 foo;foo f g
다음 Python 프로그램:
def cleaned(f):
length = len(f)
if (length % 2) == 0:
return f # even number of characters in field, middle one never ';'
half_way = length // 2
if f[half_way] != ';':
return f
before, after = f[:half_way], f[half_way+1:]
if before == after:
return before
return f
with open('tabbed.input') as fp:
for line in fp:
fields = line[:-1].split('\t')
cleaned_fields = [cleaned(f) for f in fields]
print('\t'.join(cleaned_fields))
결과는 다음과 같습니다:
012345670123456701234567012345670123456701234567
abc bd c 2000 d 2;00;2;01
e 05/19/2016 foo f g
짝수 문자를 테스트하고 필드 중간에 " "를 포함시켜 ;
중복 데이터에 " "가 포함 된 ;
경우에도 작동합니다.
답변2
POSIX적으로:
sed -e 's/\([^;][^;]*\);\1/\1/g' <file
다음을 사용할 수도 있습니다.
sed -E 's/([^;]+);\1/\1/g' <file
이는 GNU 및 BSD sed에서 지원되며 다음 POSIX 표준이 될 것입니다.
답변3
그리고 perl
:
perl -F'\t' -e 'map {s/(.+);$1/$1/} @F; print join("\t",@F)'
해당 sed
솔루션과 달리 이 솔루션은 각 필드를 개별적으로 처리하므로 필드 전체에서 중복 항목을 감지하고 제거할 가능성을 방지합니다(예 foo;<TAB>foo
: TAB 및 두 번째 필드는 foo
솔루션에 의해 제거되지만 솔루션 sed
에서는 제거되지 않음 perl
). 입력 데이터에 따라 실제 사용에는 문제가 되지 않을 수도 있습니다.
다음 버전에서는 필드(예: a;b;a;b;a;b
--> a;b
)에서 여러 중복 항목을 제거합니다.
perl -F'\t' -e 'map {while(/(.+);$1/) {s/(.+);$1/$1/g}} @F;print join("\t",@F)'
참고: 이러한 가정은 최신 버전에 대한 것으로 perl
, 이는 및 을 -F
의미합니다 . 이전 버전이 있는 경우 다음을 사용하세요.-a
-n
perl -F'\t' -ane '...'