sed를 사용하여 RSS 항목 필터링

sed를 사용하여 RSS 항목 필터링

나는 다음과 같은 스크립트를 작성하고 싶습니다:

  • 일부 RSS 피드 URL을 입력으로 사용합니다.
  • 피드를 다운로드합니다.
  • 태그가 일부 정규식과 일치하지 않는 모든 <item> ...</item>항목을 삭제합니다.title

다음 예에서는 이를 설명합니다. 다음 세 가지 항목이 포함된 RSS 피드가 있다고 가정해 보겠습니다.

  • 프로젝트 Foo - 시작해 보세요!
  • 완전히 다른 것
  • Project Foo에 대한 또 다른 업데이트

제목에 "Project Foo"가 포함된 항목만 유지하고 싶습니다.

입력 파일 예시:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>

<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Something else entirely</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

</channel>
</rss>

예제 출력 파일:

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0">
<channel>
<title>My glorious newsfeed</title>
<description>...</description>
<link>...</link>
<language>...</language>
<pubDate>...</pubDate>

<item>
<title>Project Foo - Let's get started!</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

<item>
<title>Another update on Project Foo</title>
<link>...</link>
<description>...</description>
<pubDate>...</pubDate>
</item>

</channel>
</rss>

python가능하다면 같은 도구를 사용하지 않고 명령줄 도구를 사용하여 이 작업을 수행하고 싶습니다 . 하지만 저는 등을 사용하는 큰 초보자이므로 sed도움이 필요합니다 :)

지금까지 내가 가진 것은 다음과 같습니다.

cat sample-feed.xml \
  | tr -d '\n' \
  | sed $'s/\<item\>/\\\n\<item\>/g;s/\<\/channel\><\/rss\>/\\\n\<\/channel\><\/rss\>/g' \
  | sed '/^\<item\>/ d'

먼저 모든 개행 문자를 삭제합니다. 그런 다음 줄 바꿈을 추가하여 모든 항목을 <item>...</item>자체 줄로 가져옵니다. 지금까지 마지막 명령은 로 시작하는 모든 줄을 삭제합니다 <item>. 을 위한

결과는 항목이 없는 유효한 RSS 피드입니다.

<?xml version="1.0" encoding="iso-8859-1"?><rss version="2.0"><channel><title>My glorious newsfeed</title><description>...</description><link>...</link><language>...</language><pubDate>...</pubDate>    
</channel></rss>

로컬 파일 대신 URL로 이 작업을 수행하려면 cat sample-feed.xmlcurl -s <some url>.

하지만 여전히 누락된 것은 "Project Foo"로 시작하지만 포함하지 않는 sed '/^\<item\>/ d'줄만 삭제하는 명령에 대한 수정 사항입니다 .<item>

따라서 마지막 줄이 무엇을 말해야 하는지 알아내는 데 도움을 주시면 매우 기쁠 것입니다. 반면에 이 작업을 수행하는 더 우아한 방법이 있다고 확신합니다. 내가 본 것은 매우 강력하며 하나의 명령 sed으로 이 작업을 수행하는 것이 가능할 것입니다 .sed

귀하의 답변을 기대합니다 :-)

답변1

의견에서 제안한 대로 xmlstarlet이 문제를 해결하기 위해 사용해 보았지만 잘 작동합니다. 여기 내 스크립트가 있습니다

xml ed -d '//item[not(contains(title,"Project Foo"))]' < sample_rss.xml

피드 콘텐츠가 파일에 있다고 가정해 보겠습니다 sample_rss.xml. 해당 콘텐츠는 에 공급되어 xml ed -d지정된 XPath 표현식과 일치하는 모든 메모를 삭제합니다. XPath 표현식은 텍스트를 포함하는 <item> 노드가 없는 항목을 찾습니다 .<title>"Project Foo"

이것은 잘 작동하는 것 같고 실행 시간에도 매우 만족합니다.

real    0m0.003s
user    0m0.001s
sys     0m0.002s

네임스페이스에 주의하세요

적절한 RSS 또는 Atom 피드를 사용하여 이 작업을 수행하려면 YouTube의 다음 예와 같이 feedXML 네임스페이스( ) 속성이 포함되어 있음 을 알 수 있습니다.xmlns

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom">
   ...
</feed>

그러면 위 스크립트가 더 이상 작동하지 않습니다! 이 문제를 해결하는 데 상당한 골치 아픈 일이 발생했지만 작동시키는 방법은 다음과 같습니다.

xml ed -d '//_:entry[not(contains(_:title,"Project Foo"))]' < youtube_rss.xml

이 네임스페이스 문제에 대한 자세한 내용은 여기를 참조하세요.http://xmlstar.sourceforge.net/doc/UG/ch05.html

관련 정보