Я пытаюсь декодировать файл, который в основном закодирован с помощью base64. Я хочу декодировать следующее, сохраняя при этом [_*_].
wq9cXyjjg4QpXy/Crwo=
[_NOTBASE64ED_]
aGkgdGhlcmUK
[_CONSTANT_]
SGVsbG8gV29ybGQhCg==
Иногда это будет в такой форме
aGkgdGhlcmUK[_CONSTANT_]SGVsbG8gV29ybGQhCg==
¯\_(ツ)_/¯
[_NOTBASE64ED_]
hi there
[_CONSTANT_]
Hello World!
hi there[_CONSTANT_]Hello World!
¯\_(ツ)_/¯
4��!:�@�H\�B�8ԓ��[��ܛBbase64: invalid input
base64 -di example.txt
base64 -d example.txt
base64 --wrap=0 -d -i example.txt
Я пробовал индивидуально использовать base64 для [_*_], используя grep -o. Затем найдите и
заменив их странным образом с массивами, но я не мог
заставить его работать.
base64ing все это, а затем декодирование. В результате получаются строки с двойным base64ed.
Размер файла значительно уменьшен!
Кодируется с использованием base64 --wrap=0, цикла while и оператора if / else.
[_*_] все еще должен быть там после декодирования.
Не всегда, иногда вроде wq9cXyjjg4QpXy/Crwo=[_NOTBASE64ED_]aGkgdGhlcmUK
Чем это отличается от того, что вы разместили в примере?
Это пример, когда блоки base64 в одной строке разделены [_*_]. Если вы имеете в виду, что если один блок base64 очень длинный, он переходит на новую строку, или если два находятся на одной строке без разделителя, то нет.





Вам нужен цикл, который читает каждую строку и проверяет, является ли она base64 или не-base64, и обрабатывает ее соответствующим образом.
while read -r line
do
case "$line" in
\[*\]) echo "$line" ;;
*) base64 -d <<< "$line" ;;
esac
done << example.txt
Кажется, он удаляет все, что было до [ в примере wq9cXyjjg4QpXy/Crwo=[_NOTBASE64ED_]aGkgdGhlcmUK (который я забыл добавить в исходный пост, теперь он добавлен). Также вы забыли ;; в конце *).
Я написал этот ответ до того, как вы добавили правку с [_NOTBASE64_] в середине строки.
Вероятно, это было бы проще на более мощном языке, таком как perl.
Я уверен, что у кого-то есть более умное решение, чем это. Но попробуйте это
#! /bin/bash
MYTMP1 = ""
function printInlineB64()
{
local lines=($(echo $1 | sed -e 's/\[/\n[/g' -e 's/\]/]\n/g'))
OUTPUT = ""
for line in "${lines[@]}"; do
MYTMP1=$(base64 -d <<< "$line" 2>/dev/null)
if [ "$?" != "0" ]; then
OUTPUT = "${OUTPUT}${line}"
else
OUTPUT = "${OUTPUT}${MYTMP1}"
fi;
done
echo "$OUTPUT"
}
MYTMP2 = ""
function printB64Line()
{
local line=$1
# not fully base64 line
if [[ ! "$line" =~ ^[A-Za-z0-9+/=]+$ ]]; then
printInlineB64 "$line"
return
fi;
# likely base64 line
MYTMP2=$(base64 -d <<< "$line" 2>/dev/null)
if [ "$?" != "0" ]; then
echo $line
else
echo $MYTMP2
fi;
}
FILE=$1
if [ -z "$FILE" ]; then
echo "Please give a file name in argument"
exit 1;
fi;
while read line; do
printB64Line "$line"
done < ${FILE}
и вот вывод
$ cat example.txt && echo "========================= = " && ./base64.sh example.txt
wq9cXyjjg4QpXy/Crwo=
[_NOTBASE64ED_]
aGkgdGhlcmUK
[_CONSTANT_]
SGVsbG8gV29ybGQhCg==
==========================
¯\_(ツ)_/¯
[_NOTBASE64ED_]
hi there
[_CONSTANT_]
Hello World!
$ cat example2.txt && echo "========================= = " && ./base64.sh example2.txt
aGkgdGhlcmUK[_CONSTANT_]SGVsbG8gV29ybGQhCg==
==========================
hi there[_CONSTANT_]Hello World!
Я бы предложил использовать другие языки, кроме sh, но вот решение, использующее cut. Это подойдет для случая, когда в строке находится более одного [_constant_].
#!/bin/bash
function decode() {
local data = ""
local line=$1
while [[ -n $line ]]; do
data=$data$(echo $line | cut -d[ -f1 | base64 -d)
const=$(echo $line | cut -d[ -sf2- | cut -d] -sf1)
[[ -n $const ]] && data=$data[$const]
line=$(echo $line | cut -d] -sf2-)
done
echo "$data"
}
while read -r line; do
decode $line
done < example.txt
Если Perl - вариант, вы можете сказать что-то вроде:
perl -MMIME::Base64 -lpe '$_ = join("", grep {/^\[/ || chomp($_ = decode_base64($_)), 1} split(/(?=\[)|(?<=\])/))' example.txt
Приведенный ниже код эквивалентен приведенному выше, но для объяснения разбит на шаги:
#!/bin/bash
perl -MMIME::Base64 -lpe '
@ary = split(/(?=\[)|(?<=\])/, $_);
foreach (@ary) {
if (! /^\[/) {
chomp($_ = decode_base64($_));
}
}
$_ = join("", @ary);
' example.txt
-MMIME::Base64 загружает модуль кодека base64.-lpe заставляет Perl bahave, как AWK, перебирать строки ввода и неявно обрабатывать новые строки.(?=\[)|(?<=\]) соответствует границе между блоком base64 и поддерживающим блоком, окруженным [...].split делит строку на блоки на границе и сохраняет их в массиве.
Всегда ли блоки base64 представляют собой одну строку?