2014-02-14 6 views
0

У меня есть один оператор, который необходимо заменить. Оригинальный формат, как:Заменить оператор другим с помощью сценария оболочки

f.STRING.focus(); 

Если STRING является сочетанием [:alpha:] и [:digit:] (регулярного выражения). Моя цель состоит в том, чтобы изменить его

highlight("STRING"); 

Например:

f.abCDef12345.focus() --->  highlight("abCDef12345"); 
f.ip2.focus()   --->  highlight("ip2"); 

я могу легко использовать sed заменить заявление на сотни HTML файлов. Тем не менее, я не знаю, как получить STRING в сценарии оболочки.

Процедуры могут быть описаны следующим образом:

For each html: 
    For the STRING which matches the pattern: 
     1. Assign it to a parameter. 
     2. Insert that STRING to highlight("STRING"); 
     3. Replace the old one "f.STRING.focus();" to "highlight("STRING");" 

Но я не знаю, как написать их в сценарий оболочки ... Любой намек ценится.

Обновлено:

  1. Пожалуйста, опишите ваш сценарий ясно. Большое вам спасибо!
  2. ИЗБЕГАЙТЕ ДЛЯ ОШИБКИ! STRING КОМБИНАЦИЯ И [:alpha:] и [:digit:]. Таким образом, пример, упомянутый здесь f.ip2.focus(), может иметь смысл.
+0

Не может просто используйте sed с regexp для нескольких файлов? Я не уверен, правильно ли получил эту идею. – dstronczak

ответ

2

Попробуйте этот подход:

#!/bin/bash 

while read line 
do 
    sed 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' $line 
done < <(find . -type f -name '*.html') 

Когда вы счастливы с выходом изменения SED-команды sed -i.bak вместо того, чтобы сделать рядный заменить.

Объяснение:

  1. В find команда ищет рекурсивно из текущей папки и вниз для всех файлов с именем .html
  2. Баш во время чтения цикл чтения одной строки в момент выхода из find- команда
  3. sed затем используется для поиска нужного шаблона, а шаблон \(...\) называется группой заголовков, которая хранит соответствующий текст в переменной, доступ к которой можно получить с помощью \1, которая называется обратной ссылкой ,

собственно способ читать и работать на каждой строке файла в Баш является использование

while read line 
do 
    echo $line 
done < file 

В нашем случае, мы не имеем файл, вместо этого мы хотели бы для работы в каждой строке вывода команды введите process substitution<(...) Вы можете, конечно, перенаправить команду find в файл, используя перенаправление find ... > file, а затем оперировать этим.

Update:

Как отметил @tripleee в то время как петли могут быть удалены полностью:

sed -i.bak 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' $(find . -type f -name '*.html') 

sed '...' $(find...) конструкция выполняет роль в $() в субоболочке, обеспечивая все согласования файлы в качестве параметров команды sed, как показано ниже

sed '...' ./c/file.html ./a/file.html ./b/file.html ./d/file.html 

Если у вас много html-файлов, оболочка может выдать ошибку из-за слишком длинной командной строки; если это так, то xargs - ваш друг (человек xargs).

..или (Linux полон TMTOWTDI), пусть find выполняет sed-часть для всех совпадающих файлов (по одному за раз), таким образом вы не рискуете проблемой слишком длинной командной строки :

find . -type f -name '*.html' -exec sed 's/f\.\([0-9a-zA-Z]*\)\.focus()/highlight("\1")/g' {} \; 
+0

Я не знаю, почему я должен добавлять «круглые скобки» вокруг '[: alpha:]' и что означает '(" \ 1 ")' точно означает? Кроме того, извините, я не могу выяснить последнее утверждение 'done <<(find. -type f -name '* .html')'. Пожалуйста, объясните и добавьте некоторые ссылки. – Stallman

+0

См. Обновление, это помогает? –

+0

Я все еще стараюсь, спасибо. – Stallman

0

sed -i 's/b.\(STRING\).focus()/highlight("\1")/g' file будет делать трюк

#echo "b.STRING.focus()"| sed 's/b.\(STRING\).focus()/highlight("\1")/g' highlight("STRING")

+0

Не могли бы вы предоставить дополнительные детали для вашего кода? Я полностью не могу это получить. – Stallman

+0

Как и все остальные, выражение между круглыми скобками в левой части выражения sed восстанавливается с помощью \ # в правой части –

0

An awk версия:

echo 'f.STRING.focus("Some data")' | awk '{gsub(/[[:alpha:]]\.[[:alpha:]]+\.focus\(/,"highlight(")}1' 
highlight("Some data") 

Использование sed

echo 'b.STRING.focus("Some data")' | sed 's/[[:alpha:]]\.[[:alpha:]]*\.focus/highlight/g' 
highlight("Some data") 
2
sed -i 's/f\.\([a-zA-Z0-9]\+\)\.focus()/highlight("\1")/g' file_to_process 
  1. f\. матчи f.
  2. \([a-zA-Z0-9]\+\) матчи один или несколько буквенно-цифровых символов и сохраняет совпадающая STRING в переменной 1
  3. \.focus() соответствует .focus()
  4. highlight("\1") заменяет весь подходящий шаблон с заданным текстом и значением переменной 1 ->higlight("STRING")
+0

Не соответствует предоставленной тестовой строке 'abCDef12345' –

+0

Возможно, из-за этого': alpha: 'is' a-z A-Z'? – lukk

+0

, конечно, нужно использовать '[A-Za-z0-9]' –

0

Вы можете использовать это СЭД:

sed -i.bak 's/f\.\([[:alnum:]]\+\).focus()/highlight("\1")/g' file.html 

Здесь СЭД является поиск

f.<string-with-1-and-more-alpha-numerics>.focus() 

И захват средней части в соответствии группы # 1

Он заменяющий, что с:

highlight("\1") 

Где «\ 1 'является обратной ссылкой на соответствие группы № 1

Смежные вопросы