Как сказал RedGrittyBrick, лучший способ сделать это - использовать синтаксический анализатор XML, выбрать элемент, перевести символы, а затем записать его обратно, используя библиотеку XML. Это не принесет вам неприятных сюрпризов, оно выдержит испытание временем и т.д. Это не только лучше, но и намного превосходит другие вещи. Другие решения более или менее мгновенно становятся кошмарами для отладки, и, конечно же, повсюду будут скрытые проблемы.
Если это простая задача, которую нужно выполнить один раз, и которая очень осторожна, и кто-то проверяет результат и т.д., Т. Д. И т. П., То может быть меньше работы, чтобы сделать это плохим способом. Но когда- нибудь вы удивитесь, если вы сделаете это привычкой.
Например, вот один из плохих способов, которые, кажется, работают, но он опирается не только на действительный XML, но и на более или менее точный синтаксис, который вы описали ранее, который является просто подмножеством действительного XML, и, следовательно, действительный XML, безусловно, является возможность сделать код неудачным (что если кто-то добавит знак «>» в один из тегов? Добавьте особый случай. Что делать, если кто-то не использует кавычки? Добавить специальный случай и т.д.). Это проблема не использования реального парсера. Ниже была предпринята некоторая осторожность, чтобы вести себя как минимум псевдопарсер, читая тег, затем воздействуя на него, затем записывая его обратно, но для этого есть готовые инструменты, которые были тщательно протестированы.
#!/bin/sh
IFS='\n'
while read i; do
if $(printf -- "${i}" | grep -qE '<tree [^>]+ bar="[^'"${1}"'"]*'"${1}"); then
ORIGTAG=$(printf -- "${i}" | sed 's#^.*<tree [^>]\+ bar="\([^"]\+\)".*$#\1#g')
NEWTAG=$(printf -- "${ORIGTAG}" | tr "${1}" "${2}")
printf -- "${i}\n" | sed 's#\(^.*<tree [^>]\+ bar="\)'"${ORIGTAG}"'\(".*$\)#\1'"${NEWTAG}"'\2#g'
else
printf -- "${i}\n"
fi
done < "${3}"
Использование: script.sh [символ для замены] [символ замены] [имя файла], например
script.sh c X myfile
IFS
устанавливает "внутренний разделитель полей" в оболочке на новую строку, чтобы оставить пробелы в начале строк.
while read
читает входной файл (заданный в качестве аргумента 3 для скрипта) построчно.
grep
проверяет, находится ли конкретный тег в текущей строке И если тег содержит символ для перевода. Если это так, перейдите к sed
логики; если нет, вернуть строку как есть.
sed
выбирает старый тег, запускает на нем перевод символов и возвращает строку с новым тегом.
Как видите, никто не хотел бы найти этот скрипт и отладить его. Если это что - то другое , чем работа единовременного, не делают это так. Для здравомыслия будущих наблюдателей.