Начнем с того, что я знаю, что это старый вопрос, но ни один из ответов не сработал для меня (только для busybox awk)
Два варианта. Для разбора стандартного ввода:
awk '{for (y=0;y<127;y++) if (y!=37) gsub(sprintf("%%%02x|%%%02X",y,y), y==38 ? "\\&" : sprintf("%c", y));gsub(/%25/, "%");print}'
Чтобы получить параметр командной строки:
awk 'BEGIN {for (y=0;y<127;y++) if (y!=37) gsub(sprintf("%%%02x|%%%02X",y,y), y==38 ? "\\&" : sprintf("%c", y), ARGV[1]);gsub(/%25/, "%", ARGV[1]);print ARGV[1]}' parameter
Последний должен выполнять% 25, потому что в противном случае строки типа% 253D будут подвергнуты двойному анализу, что не должно происходить.
Встроенная проверка для y == 38 объясняется тем, что gsub обрабатывает & как специальный символ, если только вы не коснитесь его.