특정 정규식을 찾고 있는데 3일 동안 노력했지만 올바른 답을 찾지 못했습니다.
XML 피드의 특정 부분을 제거해야 합니다. sed, awk를 사용해 보았지만 작동하지 않습니다.
내가 가진 것:
...Something before
<description><![CDATA[Des chercheurs de l'université de Columbia à New York ont mis au point un nouveau moyen de cacher un message dans un texte sans en altérer le sens et sans dépendre d'un format de fichier particulier. Nommée FontCode, cette idée est <a href="https://korben.info/cacher-des-informations-dans-un-texte-grace-a-des-modifications-sur-les-caracteres.html">Passage a la news suivante</a>]]></description>
... Other news
나는 필요하다:
...Something before
<description><![CDATA[Des chercheurs de l'université de Columbia à New York ont mis au point un nouveau moyen de cacher un message dans un texte sans en altérer le sens et sans dépendre d'un format de fichier particulier.<a href="https://korben.info/cacher-des-informations-dans-un-texte-grace-a-des-modifications-sur-les-caracteres.html">Passage a la news suivante</a>]]></description>
... Other news
- "<\description></description> 사이에서 여러 인스턴스를 선택하세요.
- 마지막 불완전한 문장을 제거합니다(href 앞, "Nommée FontCode, cette idée est").
당신의 도움을 주셔서 감사합니다! ;)
답변1
sed -E '/^[[:blank:]]*<description><!\[CDATA\[/s/([!?.])[^!?.<]*<a/\1 <a/' file
<description><![CDATA[
그러면 정확한 문자열 (공백이나 탭이 앞에 올 수 있음) 로 시작하는 모든 줄을 찾습니다 . 이 라인에서는 교체가 수행됩니다.
대체는 문장 종결자( [!?.]
) 뒤에 임의 개수의 문자가 오는 것과 일치합니다.아니요문장 종결자 또는 <
, 및 문자열 <a
. 이는 첫 번째 문장 종결자인 공백 및 문자열로 대체됩니다 <a
.
답변2
아래 sed 명령으로 테스트했는데 제대로 작동했습니다.
sed "s/particulier\..*<a/particulier.<a/g" file
산출
...Something before
<description><![CDATA[Des chercheurs de l'université de Columbia à New York ont mis au point un nouveau moyen de cacher un message dans un texte sans en altérer le sens et sans dépendre d'un format de fichier particulier.<a href="https://korben.info/cacher-des-informations-dans-un-texte-grace-a-des-modifications-sur-les-caracteres.html">Passage a la news suivante</a>]]></description>
... Other news
답변3
XML은 일반 텍스트 형식이지만 sed 및/또는 awk를 사용하여 이를 조작하는 것은 좋지 않습니다. 형식에는 사용 방식에 많은 특수 사례와 예외가 있으므로 이진 파일로 처리해야 합니다. 육안으로 볼 수 있는 텍스트 형식이 아닌 읽기 형식입니다. 실제로 해보기 전까지는 쉬워 보입니다. 짧은 대답은 그렇지 않습니다.
대신 XML 처리용 라이브러리가 포함된 스크립팅 언어를 사용하는 것이 좋습니다. 그러한 라이브러리가 많이 있습니다. Perl에서는 다음과 같은 작업을 수행할 수 있습니다.
#!/usr/bin/perl -wCSDA
use strict;
use warnings;
package MyFilter;
use base qw(XML::SAX::Base);
sub new {
my $class = shift;
my @args = @_;
my $self = $class->SUPER::new(@args);
$self->{indesc} = 0;
return $self;
}
sub start_element {
my $self = shift;
my $data = shift;
if ($data->{LocalName} eq "description") {
$self->{indesc} = 1;
}
return $self->SUPER::start_element($data);
}
sub end_element {
my $self = shift;
my $data = shift;
if ($data->{LocalName} eq "description") {
$self->{indesc} = 1;
}
return $self->SUPER::end_element($data);
}
sub characters {
my $self = shift;
my $data = shift;
if(($self->{indesc}) == 1) {
$data->{Data} =~ s/\.[^\.]*<a href/.<a href/;
}
return $self->SUPER::characters($data);
}
package main;
use XML::SAX::ParserFactory;
use XML::SAX::Writer;
my $writer = XML::SAX::Writer->new();
my $filter = MyFilter->new(Handler => $writer);
my $input = XML::SAX::ParserFactory->parser(Handler => $filter);
$input->parse_uri("input.xml");
작동 방식은 다음과 같습니다.
- 이
package MyFilter;
줄은 XML::SAX 필터를 구현하는 클래스를 나타냅니다.sub new
생성자이므로 실제로는$self->{indesc}
플래그만 생성합니다.sub start_element
XML 요소가 열릴 때마다 호출됩니다. 문제의 요소가 해당 요소인지 확인합니다<description>
. 그렇다면 플래그를 설정합니다(그리고 추가 처리를 슈퍼클래스에 전달합니다).sub end_element
XML 요소가 닫힐 때마다 호출됩니다. 문제의 요소가 해당<description>
요소인지 확인합니다. 그렇다면 플래그를 지우고 추가 처리를 슈퍼클래스에 전달합니다.sub characters
텍스트 또는 CDATA 요소가 처리될 때마다 호출됩니다. 이 서브루틴에서는 플래그가 설정되어 있는지 확인합니다. 그렇다면 전달된 데이터에 정규식을 적용하여 불완전한 문장을 제거합니다(점으로만 계산합니다. 이 정규식에 대한 개선 사항은 연습으로 독자에게 남습니다). -피)
- 이
main
패키지에는 스크립트의 시작점이 포함되어 있습니다.- 하나를 설정하고
XML::SAX::Writer
(기본적으로 표준 출력인 XML 형식으로 다시 전달되는 구문 분석된 XML 데이터를 출력함) 이를 필터에 연결합니다(그래서 작성자에게 전달된 XML 데이터에는 전달된 XML 데이터가 포함됩니다). 수신되고 불완전한 문장은 제거됨) 필터는 를 사용하여 생성된 XML 파서에 연결됩니다XML::SAX::ParserFactory
. - 그런 다음 전체 체인이 입력으로 전달됩니다(라는 파일에서 찾을 수 있다고 가정
input.xml
).
- 하나를 설정하고
이것이 복잡해 보인다면, 그렇기 때문입니다. 선택의 여지가 있다면 XML을 사용하지 말고 JSON이나 YAML과 같은 더 간단한 것을 사용하세요 ;-)