Назад | Перейти на главную страницу

Как правильно экранировать и интерполировать переменные в Bash?

Я пытаюсь написать однострочник для преобразования html-сущностей, присутствующих в некоторых файлах (все html с кодировкой UTF-8)

я пробовал recode HTML_4.0 file.htm но это также преобразует символы, отличные от ASCII (он разбивает символы UTF-8)

В Переполнение стека Я нашел кое-что, что работает для одного файла:

php -r '$f=@fopen("file.htm", "r");echo html_entity_decode(fread($f, 20000));fclose($f);'

но когда я пытаюсь сделать это для нескольких файлов с

for fi in *.htm; do php -r '$f=@fopen("$fi", "r");echo html_entity_decode(fread($f, 20000));fclose($f);';done

Я знаю, что проблема здесь в том, как «избежать» $ fi (переменной bash), чтобы PHP не считывал ее как переменную PHP. Любой совет?

Вы очень Где-то там.

И, как оказалось, вопрос не в том, как это сделать, а в том, как заставить bash интерпретировать переменные и передавать их.

У тебя есть:

for fi in *.htm; do php -r '$f=@fopen("$fi", "r");echo html_entity_decode(fread($f, 20000));fclose($f);';done

Который имеет одинарные кавычки с двойными кавычками внутри.

Одиночные кавычки не интерполируются внутри bash, но двойные кавычки ... поэтому, если вы измените их на:

for fi in *.htm; do php -r "\$f=@fopen(\"$fi\",'r');echo html_entity_decode(fread(\$f, 20000));fclose(\$f);"; done

Поскольку теперь мы используем двойные кавычки, нам также нужно избегать знаков $, иначе bash сочтет их интерполируемыми переменными и заменит их.

С bash (одинарные) кавычки ' используются для предотвращения расширения параметров (переменных). Таким образом, вы должны инвертировать использование одинарных и двойных кавычек в вашем вызове bash для php и добавить экранированные двойные кавычки для команды php arg:

for fi in *.htm; do fi=\"$fi\"; php -r "\$f=@fopen($fi, 'r');echo html_entity_decode(fread(\$f, 20000));fclose(\$f);"; done

Или, проще, на основе ответа Майкла Хэмптона, просто сделать:

for fi in *.htm; do cat $fi | php -R 'echo html_entity_decode($argn);'; done