Sed скрипт для поиска / замены внутри .jsp файлов. (от Struts к синтаксису JSTL EL) - PullRequest
0 голосов
/ 22 декабря 2009

Мне нужен скрипт sed, который я могу использовать для 1) поиска экземпляров и 2) печати этой строки:

<bean:write name='iframesrcUrl'/> 
<bean:write name="iframesrcUrl"/>
<bean:write name="currentPage" property="title" filter="false"/>

или аналогичный. Значения name и property могут отличаться. property и filter атрибуты являются необязательными. Встречаются как одинарные кавычки ', так и двойные кавычки ".

Команда sed должна быть двуглавой: сначала я хочу выполнить одну команду, чтобы увидеть, что она находит. Затем я хочу выполнить следующую команду, чтобы сделать фактические замены. Строки должны быть заменены на:

${ iframesrcUrl }
${ currentPage.title }

Быстрый grep показывает, что в моем проекте 68 случаев: grep '<bean:write name=' **/* |wc -l

Какой самый простой способ решить это?

Ответы [ 4 ]

1 голос
/ 22 декабря 2009

Извлекая уроки из других ответов, которые частично охватили мой вопрос, я получил следующее:

(Могу поспорить, это можно сделать короче, но это работает) моя попытка найти каждый случай таких конструкций, как

#my try to find every occurence of constructions like 
# <bean:write name='iframesrcUrl'/> 
# <bean:write name="iframesrcUrl"/>
# <bean:write name="currentPage" property="title" filter="false"/>
# 
# or similar. name and property values can differ. property and filter attributes are optional. 
# Both single quotes ' and double quotes " occur.
#
# cd jahia_virk/tomcat/webapps/ROOT/jsp/jahia/templates/virk/virk.dk


# Printing occurences:
# =====================
sed -nE \
-e '/<bean:write name="([[:alpha:]]+)"( property="([[:alpha:]]+)")( filter="false")?\/>/p' \
-e "/<bean:write name='([[:alpha:]]+)'( property='([[:alpha:]]+)')( filter='false')?\/>/p" \
-e '/<bean:write name="([[:alpha:]]+)"\/>/p' \
-e "/<bean:write name='([[:alpha:]]+)'\/>/p" \
*.jsp **/*.jsp **/*.inc  


# Replacing occurences:
# =====================
sed -E -i .bak \
-e 's/<bean:write name="([[:alpha:]]+)"( property="([[:alpha:]]+)")( filter="false")?\/>/${ \1.\3 }/g' \
-e "s/<bean:write name='([[:alpha:]]+)'( property='([[:alpha:]]+)')( filter='false')?\/>/\${ \1.\3 }/g" \
-e 's/<bean:write name="([[:alpha:]]+)"\/>/${ \1 }/g' \
-e "s/<bean:write name='([[:alpha:]]+)'\/>/\${ \1 }/g" \
*.jsp **/*.jsp **/*.inc 

Несколько уроков:

  • $ зарезервировано из командной строки, поэтому мне пришлось экранировать знак $ в строках, где выражение sed находится в двойных кавычках
  • \w не работал для сопоставления любого символа слова. Поэтому мне пришлось заменить на [[:alpha:]]
  • Подстановки в любом файле в любом каталоге (*/* **/*) не нужны для скрытых системных файлов, двоичных файлов, таких как изображения и т. Д. Мне пришлось сосредоточиться только на файлах .jsp и .inc для моего проекта: *.jsp **/*.jsp **/*.inc

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

Недостатки скрипта: По разным причинам в приведенном выше сценарии не было найдено следующих примеров:

<bean:write name='scriptEditor-Url'/>    
<bean:write name='currentSite' property='homePage.url'/>
<bean:write name="portlet" property="value" filter="false" />
<bean:write name='<%= "optTextUrl" + id %>'/>

# 1 не удалось, потому что [[:alpha:]] не соответствует - (а также есть некоторые с подчеркиванием).

# 2 - то же самое: [[:alpha:]] не соответствует точке ..

# 4 объединяет строки внутри имени параметра. Я мог бы написать сценарий, чтобы найти их, но в проекте всего четыре случая. Большой вопрос - чем его заменить? Я подозреваю, что встроенный Java не работает. и я подозреваю, что не могу просто написать ${ 'optTextUrl' + id }

0 голосов
/ 22 декабря 2009

Предполагая, что у вас есть файл типа

<root>
<bean:write name='iframesrcUrl'/> 
<bean:write name="iframesrcUrl"/>
<bean:write name="currentPage" property="title" filter="false"/>
<foo><bar/></foo>
</root>

Вы можете сделать замены с помощью этой команды sed (используя GNU sed):

 sed "s/<bean:write name=[\'\"]\?iframesrcUrl[\'\"]\?\/>/\${ iframesrcUrl }/g; \
      s/<bean:write name=[\'\"]\?currentPage[\'\"]\?.*\/>/\${ currentPage.title }/g;" \
     input.xml

, который производит:

<root>
${ iframesrcUrl } 
${ iframesrcUrl }
${ currentPage.title }
<foo><bar/></foo>
</root>

Это то, что вам нужно? Или вы хотите заменить значения атрибутов? Или вы хотите поместить текст замещения в эти теги?

Чтобы найти и отредактировать все файлы на месте (внимание! Изменяет ваши файлы, пожалуйста, перед использованием проверьте без -i, поместите маску файла вместо '* .jsp'):

find . -type f -name '*.jsp' -print0 | xargs -0 sed -i "..."

UPDATE

Чтобы заменить значения атрибутов, а не сами строки файла, я настоятельно рекомендую использовать xmlstarlet вместо sed / awk. Это гораздо надежнее и гибче. Я не могу опубликовать решение точно для вашего случая, потому что xmlstarlet нужен полный (действительный) файл для обработки, но это идея:

Данный файл:

<a>
   <b>
      <c name="foo"/>
      <c name="bar"/>
   </b>
</a>

Допустим, мы хотим заменить foo на SPAM и bar на EGGS. Затем эта команда сделает это (разделенные строки для удобства чтения):

$ printf '<a><b><c name="foo"/><c name="bar"/></b></a>' | \
  xmlstarlet ed --update "//c[@name='foo']/@name" -v SPAM \
                --update "//c[@name='bar']/@name" -v EGGS
<?xml version="1.0"?>
<a>
  <b>
    <c name="SPAM"/>
    <c name="EGGS"/>
  </b>
</a>

Я использовал синтаксис XPath для выбора элемента для замены (в первом случае это атрибут name, который принадлежит любому тегу c и равен foo). Подкоманда ed из xmlstarlet допускает различные преобразования, заменяя (обновляя) элемент только из них.

В реальных примерах вам нужно будет указать также bean рабочее пространство, то есть добавить что-то вроде

 -N bean=urn:...

к списку опций xmlstarlet. Вы можете найти правильный URI в первых строках вашего файла .jsp (мне не на что смотреть).

0 голосов
/ 22 декабря 2009

не совсем ясно, каким может быть ваш вывод. только предположение, пока вы не предоставите более четкие примеры входных и выходных данных

awk '/bean:write name/{
    $0="${ iframesrcUrl }\n${ currentPage.title }"
}{print}' file
0 голосов
/ 22 декабря 2009

Я ухожу от вашего grep regex здесь

1) Распечатать найденное

sed '/<bean:write name=/!d'

2) Заменить найденное

sed '/<bean:write name=/s/^.*$/${ iframesrcUrl }\n${ currentPage.title }/'

Глядя на ваш вопрос, я вижу, что у вас Bash4 с globstar (из-за ** / * glob). Если вы хотите, чтобы эти сценарии sed выполнялись для каждого файла рекурсивно, я бы предложил:

#!/bin/bash

for file in **/*; do
    <sed one-liner here> "$file"
done

Для замены сценария sed просто добавьте -i, чтобы выполнить редактирование на месте. Обратите внимание, что для работы требуется GNU sed. Если у вас нет GNU sed, вам придется перенаправить вывод во временный файл.

...