이전 줄이 패턴과 일치하지 않는 경우 sed를 사용하여 여러 줄 사이에 텍스트를 추가하세요.

이전 줄이 패턴과 일치하지 않는 경우 sed를 사용하여 여러 줄 사이에 텍스트를 추가하세요.

나는 <dl>정의 목록 주위에 태그를 추가하기 위해 sed를 사용하는 데 어려움을 겪고 있습니다. 어쩌면 이 작업을 수행하는 더 쉬운 방법이 있을 수도 있습니다(알고 싶습니다).

파일에서 다음을 포함하는 줄을 검색하고 싶지만 <dt>이전 줄에 다음이 포함된 경우에만 일치합니다.아니요<dt>또는 을 포함합니다 <dd>. 일치하는 항목이 발견되면 를 삽입합니다 <dl>.

지금까지 시도한 것(전혀 일치하지 않음):

sed '/^((?!<dt>).)*$/ {
    N
    /<dt>/ {
        s/<dt>/<dl><dt>/
    } 
}' file

파일도 있어요

# TODO #

 * Set up mail transfer agent
 * Reconfigure timezone

```bash
dpkg-reconfigure tzdata
```

# Hardware #
  <dt>RAM</dt>
  <dd>2GB</dd>

# Partitions #

<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>

이 모든 것의 목적은 새로운 위키 엔진으로 포팅하기 위해 moinmoin 위키 마크업을 마크다운으로 변환하는 파서를 작성하는 것입니다. 현재 정의 목록은 다음 규칙에 따라 개발되었습니다.

sed -i 's/^ \(.*\):: \(.*\)$/  <dt>\1<\/dt>\n  <dd>\2<\/dd>/' file

출력이 다음과 같기를 원합니다.

# TODO #

 * Set up mail transfer agent
 * Reconfigure timezone

```bash
dpkg-reconfigure tzdata
```

# Hardware #
<dl>
  <dt>RAM</dt>
  <dd>2GB</dd>
</dl>

# Partitions #

<dl>
<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>
</dl>

가능한 한 유효한 HTML을 원합니다. 모든 여는 태그에는 종료 태그가 있어야 합니다.

답변1

이는 여러분이 기대하는 것 이상일 수 있지만 sed원하는 것을 달성하는 가장 좋은 방법이라고 생각합니다 sed.

이 스크립트는 다음과 같습니다.

  • 행 앞에 다른 , 또는 가 없으면 <dl>포함된 각 행 앞에 행이 삽입됩니다.<dt><dt><dd><dl>

  • </dl>포함된 줄 다음의 줄이 포함되지 않으면 <dd>포함된 각 줄 뒤에 한 줄이 추가됩니다.<dd><dd>

스크립트 는 태그를 삽입하기 전에 태그를 확인할 수 있도록 공백을 sed사용하여 이전 줄을 기억합니다 . 또한 닫는 태그를 추가할 수 있도록 상대 주소 지정을 사용합니다 . a가 파일의 마지막 줄에 있고 추가되어야 하는지를 감지하려면 특별한 경우가 필요합니다 . test( 및 ) 및 Branch( )는 논리를 구현하는 데 널리 사용됩니다.sed hold<d[tdl]><dl>ADDR,+N</dl><dd></dl>tTb

#!/bin/sh

sed '
    /<dt>/ {
        x                  # exchange pattern and hold space
        s/<d[tdl]>//       # subsitutue, just testing for pattern
        g                  # copy hold space back, overwriting pattern space
        t end              # branch to :end if previous subsitution successful
        i \
<dl>
    }

    $ {
        /<dd>/ ! b end     # if <dd> on last line, append </dl>
        a \
</dl>
    }

    /<dd>/,+1 {            # on each line containing <dd> and the line after
        /<dd>/ b end       # if does not contain <dd>, insert </dl>
        i \
</dl>
    }

:end
    h                      # copy pattern space to hold space for next round

' "$@"

스크립트는 샘플 데이터를 다음과 같이 수정합니다.

[...]

# Hardware #
<dl>
  <dt>RAM</dt>
  <dd>2GB</dd>
</dl>

# Partitions #

<dl>
<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>
</dl>

관련 정보