![sed를 사용하여 RSS 항목 필터링](https://rvso.com/image/1605160/sed%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20RSS%20%ED%95%AD%EB%AA%A9%20%ED%95%84%ED%84%B0%EB%A7%81.png)
나는 다음과 같은 스크립트를 작성하고 싶습니다:
- 일부 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.xml
를 curl -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의 다음 예와 같이 feed
XML 네임스페이스( ) 속성이 포함되어 있음 을 알 수 있습니다.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