2016-05-24 2 views
1

Предположим, что существует один file.txt, в котором написан текст, как указано ниже: -Shell Script, чтобы заполнить цели, определенные в файле XML

ABC 
EFG 
XYZ 

В другой XML, есть один пустой целевой орган по имени (компилировать).

<project> 
<compile> 
. 
. 
. 
start  //from here till EOF 
shell 
script 
xyz 
</compile> 
</project> 

Мне нужен сценарий оболочки, который заполняет контент между заданной целью. После выполнения скрипта он должен выглядеть так, как указано ниже в теге output.It будет сделан для всего содержимого, записанного в файле file.txt.

Выход: -

<!-- ...preceding portions of input document... --> 
<project> 
<compile> 
componentName="ABC" 
componentName="EFG" 
componentName="XYZ" 
start  
shell 
script 
xyz 
</compile> 
</project> 
<!-- ...remaining portions of input document... --> 

ответ

0

Вы можете делать то, что вы пытаетесь (до некоторой степени) с sed и while read -r петли. Например, вы можете заполнить временный файл с содержимым файла XML из строки 1 в <targettag> с

sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag 

(где xfn ваше имя файла XML и ofn это имя файла, на выходе)

Вы можете прочитать все значения из текстового файла и предварять componentName=" и добавить " с:

while read -r line; do ## read each line in ifn and concatenate 
    printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn" 
done <"$ifn" 

(где ifn ваш входной файл на я)

И, наконец, вы можете написать закрывающий тег конец файла XML в свой выходной файл с:

sed -n "/^${ttag/</<[\/]}$/, \${p}" "$xfn" >> "$ofn" 

(с использованием расширения параметров с заменой подстроки добавить закрытие '/' к начало <targettag>.

Собираем в целом, вы могли бы сделать что-то вроде:

#!/bin/bash 

ifn="f1" 
xfn="f2.xml" 
ofn="f3.xml" 

ttag="${1:-<targettag>}" ## set target tag 
cmptag="componentName=\"" ## set string to prepend 

sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag 

while read -r line; do ## read each line in ifn and concatenate 
    printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn" 
done <"$ifn" 

## fill output from closing tag to end 
sed -n "/^${ttag/</<[\/]}$/, \${p}" "$xfn" >> "$ofn" 

входных файлов

$ cat f1 
ABC 
EFG 
XYZ 

$ cat f2.xml 
<someschema> 
<targettag> 
</targettag> 
</someschema> 

Пример использования/вывода

$ fillxml.sh 

$ cat f3.xml 
<someschema> 
<targettag> 
componentName="ABC" 
componentName="EFG" 
componentName="XYZ" 
</targettag> 
</someschema> 

(вы можете настроить инден тации в соответствии с вашими потребностями)


Добавления После изменений на вопрос

изменения, необходимого для обработки письменной формы от start до конца после добавления componentName="..." тегов просты. Однако общность слова start иллюстрирует, почему ответ Чарльза рекомендует использовать инструмент XML, а не простой скрипт. Зачем?Если слово «start» происходит где-либо еще в вашем файле .xml до вашего предполагаемого start, сценарий завершится неудачей, записав для первого вхождения start в конец.

Тем не менее, если это простой двухпозиционный преобразования и start не происходит иначе, то изменения в сценарий, чтобы достигнуть нужного вывода легко:

#!/bin/bash 

ifn="f1" 
xfn="another.xml" 
ofn="f3.xml" 

ttag="${1:-<compile>}" ## set target tag 
cmptag="componentName=\"" ## set string to prepend 

sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag 

## read each line in ifn and concatenate 
while read -r line || [ -n "$line" ]; do 
    printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn" 
done <"$ifn" 

## fill output from 'start' to end 
sed -n "/^start/, \${p}" "$xfn" >> "$ofn" 

Входные файлы

$ cat f1 
ABC 
EFG 
XYZ 

$ cat another.xml 
<project> 
<compile> 
start 
shell 
script 
xyz 
</compile> 
</project> 

Пример использования/выход

$ cat f3.xml 
<project> 
<compile> 
componentName="ABC" 
componentName="EFG" 
componentName="XYZ" 
start 
shell 
script 
xyz 
</compile> 
</project> 

Посмотрите и сообщите мне, если у вас есть вопросы.

+0

Есть * тааак * много случаев, когда это будет вести себя плохо. Что делать, если '' также отображается внутри раздела CDATA или комментария? Что делать, если оно находится в псевдониме? Что делать, если одна из заменяемых строк должна быть экранирована, чтобы быть допустимым XML? Что делать, если кто-то добавляет атрибут к этому тегу, делая его ''? –

+0

Согласовано. Я не сторонник разбора xml с bash по всем причинам, которые вы цитируете (таким образом, квалификация «в некоторой степени»). Для этого ограниченного случая, конечно, как обобщение, нет. –

+0

thnx @ DavidC.Rankin для решения, но с этим решением мне нужно также выполнить мое требование. После того как вы создали окончательный xml со всей строкой componentName и когда вы собираетесь закрыть цель. Я не хочу закрывать тег, хотя я хочу скопировать еще текст перед закрытием цели и после имени компонента. Можете ли вы, пожалуйста, помочь команде скопировать текст из определенного содержимого, написанного в f2.xml, позволяет сказать, что слово «start» написано в f2.xml, и я хочу скопировать из этого слова в EOF в f3.xml, когда я создал f3.xml до имени компонента. – user6376225

1

Используйте правильный синтаксический анализатор XML. XMLStarlet один инструмент, пригодный для работы:

#!/bin/bash 
#  ^^^^- important, not /bin/sh 

# read input file into an array 
IFS=$'\n' read -r -d '' -a pieces <file.txt 

# assemble target text based on expanding that array 
printf -v text 'componentName=%s\n' "${pieces[@]}" 

# Read input, changing all elements named "compile" in the default namespace 
# ...to contain our target text. 
xmlstarlet ed -u '//compile' -v "$text" <in.xml >out.xml 
Смежные вопросы