Заменить оператор другим сценарием оболочки

У меня есть одно утверждение, которое нужно заменить. Исходный формат выглядит так:

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() может иметь смысл.

5 ответов

Решение

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

#!/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 вместо этого сделать inline-replace.

Объяснение:

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

Правильный способ чтения и работы с каждой строкой файла в bash - использовать

while read line
do
    echo $line
done < file

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

Обновление:

Как указывает @tripleee, цикл while можно полностью удалить:

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' {} \;
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")

sed -i 's/b.\(STRING\).focus()/highlight("\1")/g' file сделает свое дело

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

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

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

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")
Другие вопросы по тегам