sed는 이미지 경로를 대체합니다.

sed는 이미지 경로를 대체합니다.

디렉토리에 있는 여러 xhtml 파일의 이미지 경로를 바꿔야 합니다. 파일 헤더 부분은 다음과 같습니다.

<?xml version="1.0" encoding="UTF-8"?>
<html xml:lang="en-us" lang="en-us" xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:ns="http://www.w3.org/2001/10/synthesis">
<head>

명령으로 시도했지만 sed성공하지 못했습니다. 특정 sed 버전 때문일 수도 있지만 확실하지는 않습니다. 나는 가지고있다GNU sed 4.4

original path:
<img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"
I need replace to:
<img src="graphics/line.jpg"

나는 노력했다

sed -i '.bak' 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' '*.xhtml'

그것은 돌아온다

sed: -e expression #1, char 1: unknown command: `.'

또한 시도

sed -i ' ' 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' '*.xhtml'
it return
sed: can't read s/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g: No such file or directory
sed: can't read *.xhtml: No such file or directory

sed이것이 적합합니까?

답변1

sed유틸리티는 일반적으로 XML 또는 XHTML 파일을 편집하는 데 적합하지 않습니다. XML은 구조화된 문서 형식이며 줄 중심이 아닙니다. 많은 표준 Unix 텍스트 조작 도구와 마찬가지로 이 sed유틸리티는 라인 지향적이며 추가 노력 없이는 XML 엔터티 인코딩 또는 디코딩과 같은 작업을 처리할 수 없습니다.

예제 문서에는 노드가 포함되어 있습니다( />끝 부분에 포함되도록 수정됨)

<img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg" />

img노드 내의 공백(공백, 탭 및 줄 바꿈)은 임의적이며 노드의 추가 속성 이나 순서를 알 수 없으므로 노드 속성의 경로 이름 sed외에도 다음을 확인해야 합니다. src, 다른 곳에서는 경로 이름을 바꾸지 마십시오 img.

명령줄 XML 파서를 사용하여 이를 수행하는 방법은 다음과 같습니다.

xmlstarlet ed   \
        -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]' \
        -v 'graphics/line.jpg' file.xhtml

우리는 xmlstarlet꽤 잘 알려진 명령줄 XML 파서인 를 사용하여 src속성의 원래 값이 이면 각 노드의 각 속성 값을 문자열로 대체합니다.imggraphics/line.jpg/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg

이 명령은 작업 결과를 표준 출력에 기록하지만 테스트 후 해당 (또는) 옵션을 사용하여 xmlstarlet예상대로 작동하는지 확인할 수 있습니다.--inplace-L


태그가 올바른 끝 없이 img처럼 보이는 경우 먼저 XHTML 파일을 필터링하여 이를 되돌릴 수 있습니다.<img src="...">

xmlstarlet fo --recover --html file.xhtml

형태에 파이프가 있다고 상상할 수도 있습니다.

xmlstarlet fo --recover --html file.xhtml |
xmlstarlet ed   \
        -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]' \
        -v 'graphics/line.jpg'

처리하려는 파일이 모두 패턴과 일치하는 경우 ./*.xhtml, 즉 .xhtml파일 이름 접미사가 있고 현재 디렉터리에 있는 경우 위 명령 중 하나를 사용하여 간단한 쉘 루프를 사용하여 모든 파일을 처리할 수 있습니다. .

for name in ./*.xhtml; do
        xmlstarlet ed --inplace        \
                -u '//img/@src[. = "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"]'   \
                -v 'graphics/line.jpg' "$name"
done

이는 백업을 만들지 않고 파일을 수정하는 --inplace옵션을 사용한다는 점에 유의하세요. xmlstarlet백업 데이터에서 이 작업을 실행하는 것이 가장 좋습니다.

디렉터리 계층 구조(예: 여러 하위 디렉터리가 있는 디렉터리)의 모든 XHTML 파일에 대해 위 명령을 실행하려면 를 사용할 수 있습니다 find.

find . -type f -name '*.xhtml' -exec sh -c '
        for name do
                xmlstarlet ed --inplace        \
                        -u "//img/@src[. = \"/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg\"]" \
                        -v "graphics/line.jpg" "$name"
        done' sh {} +

답변2

XHTML인 경우 적절한 XML 편집기를 사용하여 편집할 수 있습니다. 이것의 장점은 파일 레이아웃 변경에 영향을 받지 않는다는 것입니다.

먼저 예제를 XML로 수정합니다(결국 XHTML 문서입니다).

<img src="/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg"/>

소스 문서가 실제 XHTML이 아닌 경우 프로그래밍 방식으로 수정할 수 있습니다.

xmlstarlet format -H file.xhtml

src다음 명령을 사용하여 속성을 편집 할 수 있습니다 xmlstarlet.

xmlstarlet edit --omit-decl --update '//img/@src' --value 'graphics/line.jpg' file.xhtml
<img src="hello"/>

또는 이 두 명령을 결합하여

xmlstarlet fo -H file.xhtml 2>/dev/null |
    xmlstarlet ed -u '//img/@src' -v 'graphics/line.jpg'

준비가 되면 결과를 임시 파일에 저장하고 원본 파일을 수정된 버전으로 바꿉니다. (또는 원본 파일의 이름을 백업으로 바꾸고 이를 입력으로 사용하여 원본 이름의 파일을 생성합니다.)

요소가 여러 개 있는 경우 <img/>단순히 . 그러나 귀하의 질문에는 이러한 가능성을 효과적으로 해결하기 위한 세부 정보가 충분하지 않습니다.//imgsrc

답변3

노력하다:

sed -i.bak 's/\/api\/v2\/epubs\/urn:orm:book:381260143574\/files/graphics/g' *.xhtml


sed -i '.bak' --> sed -i.bak
'*.xhtml' --> *.xhtml

슬래시를 이스케이프 처리하고 싶지 않은 경우 다른 옵션은 를 사용하는 것입니다 rpl.

Debian 기반 배포판의 경우:

sudo apt install rpl

rpl -b "/api/v2/epubs/urn:orm:book:381260143574/files/line.jpg" "graphics/line.jpg" *.xhtml

-b = backup

rpl 매뉴얼

답변4

당신은 또한 이것을 시도할 수 있습니다 sed. -i테스트하는 동안 적합하지 않기 때문에 해당 플래그를 포함하지 않았습니다 .

sed -E 's|(img src=").[^"]*(/.*)|\1graphics\2|' input_file

이렇게 하면 유지해야 하는 일치 항목을 그룹화하고 유지하지 않아도 되는 일치 항목은 제외합니다.

(.*=.)- 마지막 발생까지 모든 것을 그룹화=

.[^"]*- 제외된 일치 항목입니다. [^"]마지막 항목과 일치 /하고 다음 항목과 일치하는 것을 방지하는 데 사용됩니다."

(/.*)- 마지막 두 번째 패턴까지 모두 /제외되었으며, 그 이후의 나머지 패턴은 일치됩니다.

\1graphics\2- 두 개의 그룹 경기가 생성되었으며 순서에 관계없이 반환할 수 있습니다. graphics나중에 하드코딩해야 하므로 그룹화 =된 첫 번째 일치 항목이 반환되자마자 삽입할 수 있습니다.\1

|- 데이터 자체에 "/" 슬래시가 포함되어 있어 seds기본 구분 기호와 충돌하므로 파이프를 구분 기호로 사용합니다.

산출

$ sed -E 's|(img src=").[^"]*(/.*)|\1graphics\2|' input_file
<img src="graphics/line.jpg"/>

관련 정보