디렉토리에 있는 여러 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
속성의 원래 값이 이면 각 노드의 각 속성 값을 문자열로 대체합니다.img
graphics/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/>
단순히 . 그러나 귀하의 질문에는 이러한 가능성을 효과적으로 해결하기 위한 세부 정보가 충분하지 않습니다.//img
src
답변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
답변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"/>