В общем, HTML не может быть правильно проанализирован с помощью регулярных выражений, но если у вас есть определенный ограниченный формат, он может работать.
Учитывая простой формат, такой как
<body>
<img src="data:image/jpeg;base64,DpFDPGOIg3renreGR43LGLJKds==">
<img src="data:image/jpeg;base64,DpFDPGOIg3renreGR43LGLJKds=="><img src="data:image/jpeg;base64,DpFaPGOIg3renreGR43LGLJKds==">
<div><img src="data:image/jpeg;base64,DpFdPGOIg3renreGR43LGLJKds=="></div>
</body>
следующие данные могут извлечь данные
i=0; awk 'BEGIN{RS="<"} /="data:image\/jpeg;base64,[^\"]*"/ { match($0, /="data:image\/jpeg;base64,([^\"]*)"/, data); print data[1]; }' test.html | while read d; do echo $d | base64 -d > $i.jpg; i=$(($i+1)); done
Чтобы разбить это на части:
i=0
Сохраните счетчик, чтобы мы могли выводить разные имена файлов для каждого изображения.
awk 'BEGIN{RS="<"}
Запустите awk с разделителем записей, измененным с новой строки по умолчанию на <, поэтому мы всегда обрабатываем каждый элемент HTML как отдельную запись. </p>
/="data:image\/jpeg;base64,[^\"]*"/
Выполняем только следующие команды для записей, в которые встроены данные JPEG в формате base64.
{ match($0, /="data:image\/jpeg;base64,([^\"]*)"/, data); print data[1]; }'
Извлеките сами данные, часть, соответствующую скобкам между запятой и конечной кавычкой, затем напечатайте их.
test.html
Только имя файла ввода.
| while read d; do
Передать выходные данные base64 в цикл.read
будет помещать каждую строку в d
до тех пор, пока не прекратится ввод.
echo $d | base64 -d > img$i.jpg;
Передать текущее изображение через декодер base64 и сохранить вывод в файл.
i=$(($i+1));
Инкремент для изменения следующего имени файла.
done
Готово.
Есть несколько вещей, которые можно было бы сделать лучше здесь:
- Должно бытьспособ получить регулярное выражение соответствия строки для непосредственного захвата данных base64, вместо повторения регулярного выражения при вызове функции
match()
, но я не смог заставить его работать. - Я не знаюЭто не похоже на технику чтения канала в переменную d только для вывода его обратно в другой канал - было бы лучше просто передать прямо через канал - но
base64
не знает, использовать только одну строку ввода. - По какой-то причине я еще не понял, увеличивая счетчик непосредственно там, где он используется (то есть
echo $d | base64 -d > img$((i++)).jpg
), записывая только в первый файл, даже если echo $d > img$((i++)).b64
правильно записал закодированные данные в несколько файлов.Вместо того чтобы ждать, пока я это решу, я просто разделил приращение на собственную команду.