sed 인라인은 XML 스타일 입력을 수정할 수 없습니다

sed 인라인은 XML 스타일 입력을 수정할 수 없습니다

문제는 전체 명령을 SED와 같은 줄에 넣을 수 없다는 것입니다. 그렇게 했지만 다음 파일에서는 작동하지 않습니다. 내 예:

<file>Documents/time/text1</file> //2X slash + 2 words to remove !!
<file>Commun/text2</file>         //1X slash to remove + 1 words to remove
<file>Current/text3</file>        //1X slash to remove + 1 words to remove

이 코드가 온라인에서 작동하지 않는 이유는 무엇입니까?

sed 's/Documents//g' | sed 's/time//g' | sed 's/Commun//g' | sed 's/Current//g' | sed 's/Current//g' | sed '/<file>/s|<file>/|<file>|' | sed '/<file>/s|<file>/|<file>|' tracklist.txt > newtracklist.txt

답변1

OP의 현재 스크립트 파이프라인을 실행하면 입력 파일( )의 내용이 stdout으로 인쇄된 다음 파이프라인이 중단 sed됩니다 tracklist.txt(즉, 다른 출력이 없거나 명령 프롬프트로 돌아가지 않음). 그래요추측하다OP가 언급할 때 언급한 내용입니다.it does not work... ??

주요 문제: 입력 파일( )은 마지막 스크립트 가 아닌 첫 번째 스크립트 tracklist.txt에 대한 인수로 제공되어야 합니다 .sedsed

추천하다:

# instead of this:

sed 's/Documents//g'               | ... |  sed '/<file>/s|<file>/|<file>|' tracklist.txt
                                                                            ^^^^^^^^^^^^^
# do this:

sed 's/Documents//g' tracklist.txt | ... |  sed '/<file>/s|<file>/|<file>|'
                     ^^^^^^^^^^^^^

sedOP 파이프라인의 업데이트된 버전을 실행하면 다음이 생성됩니다.

<file>text1</file>
<file>text2</file>
<file>text3</file>

HTML/XML을 구문 분석하기 위한 더 나은 도구가 있지만 OP가 이를 사용해야 하는 경우 sed더 효율적인 방법으로 동일한 결과를 생성할 수 있는 방법이 있습니다.

아이디어에는 sed스크립트가 필요합니다.

sed -E 's|(<file>).*/([^/]+</file>)|\1\2|' tracklist.txt

어디:

  • -E- 확장 정규식 지원 활성화
  • (<file>)- (첫 번째 캡처 그룹) 문자열과 일치합니다.<file>
  • ([^/]+</file>)- (두 번째 캡처 그룹) /뒤에 문자열이 없는 모든 문자 와 일치합니다.</file>
  • .*/- 두 캡처 그룹 사이의 모든 것은/
  • \1\2- 대체 문자열은 함께 추가된 두 개의 캡처링 그룹으로 구성됩니다.
  • 노트:이는 OP에서 제공하는 특정 입력에 대해 작동합니다. 입력이 OP의 예시 입력에 표시된 것과 다른 형식인 경우 조정이 필요할 수 있습니다.

OP의 샘플 입력의 경우 다음이 생성됩니다.

<file>text1</file>
<file>text2</file>
<file>text3</file>

답변2

입력 XML 파일이 주어지면

r루트 노드 추가 :

<r>
    <file>Documents/time/text1</file>
    <file>Commun/text2</file>
    <file>Current/text3</file> 
</r>

암호:

xidel --xquery '
    <r>{
        for $x in //file
        return <file>{tokenize($x, "/")[last()]}</file>
    }</r>
' --output-format=xml --output-node-indent file.xml

생산하다:

<?xml version="1.0" encoding="UTF-8"?>
<r>
  <file>text1</file>
  <file>text2</file>
  <file>text3</file>
</r>

설명하다:

여기서는 sed잘못된 도구를 사용하는 대신 올바른 구문 분석기를 사용하고 있습니다 XPath( XQuery전자는 후자의 하위 집합입니다) XML.

xidelHTML/XML 작업의 스위스 군용 칼입니다.

용법:

xidel ... file.xml > new_file.xml

편집하고 싶다면비행 중:

xidel ... file.xml | sponge file.xml

sponge~에서암소 비슷한 일종의 영양 more-utils.

답변3

사용행복하다(이전 Perl_6)

~$ raku -MXML -e 'my  $xml = open-xml( $*ARGFILES.Str );
                  for $xml.elements( :RECURSE(0), :TAG{"file"} ) -> $E {
                      my $old = $E.contents[0];
                      my $new  = XML::Text.new( text => $old.text.match(/ <?after "/">  <-[/]>+  $/) );
                      $E.replace( $old, $new );
                  };  .say for $xml;'   file.xml

또는:

% raku -MXML -e 'my  $xml = open-xml( $*ARGFILES.Str );
                 for $xml.elements( :RECURSE(0), :TAG{"file"} ) -> $E {
                      my $old = $E.contents[0];
                      my $new  = XML::Text.new( text => $old.text.path.basename );
                      $E.replace( $old, $new );
                  };  .say for $xml;'   file.xml

Raku는 고급 기능을 갖춘 Perl 제품군의 프로그래밍 언어입니다.문법텍스트를 구문 분석하는 데 사용됩니다. Raku/Rakudo 자체 외에도 커뮤니티 구성원은 Raku/Rakudo 생태계의 모듈을 지원합니다. 이러한 모듈 중 하나는 (라쿠 출신) XML모듈.

OP의 다른 질문과 유사하게 XML-module을 사용하는 Raku에서는 (예를 들어) 교체를 1로 제한할 수 있습니다. 최상층 및 2). TAG 내에서만 가능합니다 <file>. 이는 elements제약 조건 내에서 반복 하도록 코드를 설정하여 수행됩니다 :RECURSE(0), :TAG{"file"}. 참고로, TAG필요한 경우 모든 깊이에서 모든 s를 반복할 수 있습니다. 명명된 인수를 설정 :RECURSE(Inf)하고 제거하면 제한이 False로 설정됩니다.:TAG:TAG

위의 첫 번째 대답은 교체에 적합한 태그/수준을 식별합니다. 이는 각 요소의 내부 부분(즉, TAG가 아닌 부분)이 실제로 객체인 contents[0]변수에 할당되었음을 확인합니다 . 객체를 문자열로 추출하고 원하는 객체를 찾습니다. 이제 수정된 키/값 쌍을 사용하여 새( ) 객체를 생성( )합니다 . 이제부터 -module의 루틴이 작업을 수행합니다.$oldXML::Text$old.textmatchXML::Text.new$newtext => 'value'XMLreplacereplace( $old, $new )

위의 두 번째 답변은 첫 번째 답변을 영리하게 변형한 것입니다. OP는 경로 이름을 편집하려고 하기 때문에 IO::PathRaku 개체 클래스와 관련된 루틴을 사용할 수 있습니다. Raku의 .IO루틴은 텍스트를 유효한 경로 이름으로 이해하고 Raku의 .basename루틴은 최종 파일 이름을 반환합니다. Raku에는 다양한 플랫폼에서 올바른 ( /또는 \) 경로 구분 기호를 사용하는 메커니즘이 있으므로 이 접근 방식은 코드 이식성을 향상시킬 수 있는 잠재력이 있습니다.

입력 예(@GillesQuénot에게 감사드립니다!):

<r>
    <file>Documents/time/text1</file>
    <file>Commun/text2</file>
    <file>Current/text3</file>
</r>

예제 출력:

<?xml version="1.0"?><r>
    <file>text1</file>
    <file>text2</file>
    <file>text3</file>
</r>

https://github.com/raku-community-modules/XML
https://docs.raku.org/type/IO/Path
https://rakudo.org/
https://raku.org

관련 정보