POSIX 정규식 세트가 있습니다*
^BEGIN:VCARD\r$
^VERSION[^A-Z]
^FN[^A-Z]
^N[^A-Z]
^NICKNAME[^A-Z]
^EMAIL[^A-Z]
^X-\([A-Z-]*\)
^TEL[^A-Z]
^ADR[^A-Z]
^ORG[^A-Z]
^TITLE[^A-Z]
^BDAY[^A-Z]
^URL[^A-Z]
^ROLE[^A-Z]
^NOTE[^A-Z]
^END:VCARD\r$
그리고 각 줄이 정규식 중 하나와 일치하는 파일은 다음과 같습니다.
BEGIN:VCARD
VERSION:3.0
N:Doe;Jane;;Ms;
URL:http://janedoe.com/
EMAIL:[email protected]
EMAIL:[email protected]
BDAY:1970-01-01
X-JABBER:[email protected]
X-ICQ:1234567890
END:VCARD
이 행을 기준으로 정렬하고 싶습니다.
- 정규식과 일치하는 줄 번호(FN으로 시작하는 줄이 N으로 시작하는 줄 앞에 오도록),
- 일치 그룹(X-ABC가 X-DEF 앞에 오도록)
이상적으로는 행의 다른 부분은 정렬되지 않아야 합니다. 따라서 EMAIL로 시작하는 행의 순서가 유지되어야 합니다. 따라서 예상되는 결과는 다음과 같습니다.
BEGIN:VCARD
VERSION:3.0
N:Doe;Jane;;Ms;
EMAIL:[email protected]
EMAIL:[email protected]
X-ICQ:1234567890
X-JABBER:[email protected]
BDAY:1970-01-01
URL:http://janedoe.com/
END:VCARD
이를 수행할 수 있는 기존 도구가 있습니까?
편집하다:구현 결과기반으로Lars Rohrbach의 답변.
* Gmail 연락처 내보내기 파일의 vCard 속성 순서입니다.
답변1
일반적인 sort
명령은 포함할 특정 "사전"을 지정하는 방법을 제공하지 않으며, 명령을 사용하면 grep
정규식 파일을 제공할 수 있지만 출력 순서는 변경되지 않습니다. 그러나 두 가지를 간단한 foreach
루프에 넣을 수 있습니다. 다음은 bash 셸에서 실행되는 예입니다.
for i in `cat fileofregexp`; do grep "$i" myinputfile; done
이는 정규식 파일의 각 정규식 행을 하나씩 가져와 입력 파일에서 일치하는 항목을 출력하므로 결과 출력은 정규식 순서로 정렬됩니다. 정확하게 일치하지 않는 입력 파일의 행은 출력에 표시되지 않습니다.
부록:요청에 따라 루프를 사용하는 버전은 다음과 같습니다 while
.
while IFS= read -r i; do grep "$i" myinputfile; done < fileofregexp
답변2
정확히 이렇게 프레임을 구성한 것은 아니지만, 실제 목적을 고려하면 콜론 앞 부분을 잡아서 정렬하는 것이 더 간단할 것입니다. 다음은 별도의 정렬 키에서 별도의 배열 항목으로 행을 누적하고 끝에 도달하면 vcard를 플러시하는 Perl 스크립트입니다.
#!/usr/bin/perl -n
BEGIN {
@headers = qw(BEGIN VERSION FN N NICKNAME EMAIL X- TEL ADR ORG TITLE BDAY URL ROLE NOTE END);
for $h (@headers) { $data{$h} = ""; }
}
if (/^([^:]+):/) {
$data{exists $data{$1} ? $1 : "X-"} .= $_;
if ($1 eq 'END') {
for $h (@headers) { print $data{$h}; $data{$h} = ""; }
}
} else {
print;
}
완전한 정규식 유연성을 정말로 원한다면 해시에서 키를 찾는 대신 정규식을 반복하십시오.
#!/usr/bin/perl -n
BEGIN {
@regexps = qw(^BEGIN:VCARD\r$ ^VERSION[^A-Z] ^FN[^A-Z] ^N[^A-Z] ... ^END:VCARD\r$);
for $r (@regexps) { $data{$r} = ""; }
}
for $r (@regexps) {
next unless $_ =~ $r;
$data{$r} .= $_;
last;
}
if ($_ =~ $regexps[@regexps-1]) {
for $r (@regexps) { print "++", $data{$r}; $data{$r} = ""; }
}