Заменить оператор другим сценарием оболочки
У меня есть одно утверждение, которое нужно заменить. Исходный формат выглядит так:
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");"
Но я не знаю, как написать их в сценарии оболочки... Любая подсказка приветствуется.
Обновлено:
- Пожалуйста, опишите ваш сценарий четко. Большое спасибо!
- ИЗВИНИТЕ ЗА ОШИБКУ!
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.
Объяснение:
find
Команда ищет рекурсивно из текущей папки и вниз для всех файлов с именем.html
- Цикл bash while-read читает по одной строке за раз выходных данных команды find
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
f\.
Матчиf.
\([a-zA-Z0-9]\+\)
соответствует одному или нескольким буквенно-цифровым символам и соответствует магазинамSTRING
в переменной1
\.focus()
Матчи.focus()
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")