Указанный для печати стандарт кодирования определен как часть RFC 2045
.
Для краткого изложения и в общем смысле: непечатные символы ASCII кодируются как три -последовательность символов, начинающаяся с "="
, за которой сразу следует шестнадцатеричное число, состоящее из двух цифр git, что соответствует коду ASCII-символа; "="
само кодируется таким же образом; строки могут быть длиной до 76 символов, но не более 76 символов, для которых "="
действует как символ продолжения (или мягкого переноса), если он появляется в конце строки.
Я взял расширенный набор этих правил, обеспечивающий выполнение достаточных условий, вокруг которых был написан следующий сценарий, и представлен «как есть» без каких-либо особых попыток оптимизации (для которых еще остается область действия):
#!/usr/bin/env osascript
--------------------------------------------------------------------------------
use framework "Foundation"
use scripting additions
--------------------------------------------------------------------------------
prop NSString: ref current application's NSString
prop rgex: 1024
prop utf8: 4
--------------------------------------------------------------------------------
on qp_decode(input)
local input
try # test for existence as a file path
input as «class fsrf»
NSString's stringWithContentsOfURL:result ¬
encoding:utf8 |error|:(missing value)
on error
input
end try
set qp to __s(result)
replace(qp, "(?m)\\h*$", "") # Removing trailing whitespace
replace(qp, "(?sm)=(\\R|$)", "") # Join lines split with a soft-break
map(qp, "(?i)=[A-F0-9]{2}", char) # Decode escape sequences, i.e. "=HH"
end qp_decode
--------------------------------------------------------------------------------
# "PRIVATE" HANDLERS:
on __s(init)
ref item 1 of {init}
end __s
to _nsstring_ from _ref given mutability:m as boolean : false
local _ref, m, t
set t to NSString's stringWithString:_ref
if m then set t to t's mutableCopy()
try
set _ref's contents to t
end try
t
end _nsstring_
to replace(_ref, a, b)
local _ref, a, f, t
set t to _nsstring_ from _ref with mutability
t's replaceOccurrencesOfString:a withString:b ¬
options:rgex |range|:{0, t's |length|()}
try
set _ref's contents to t as text
end try
t as text
end replace
to map(_ref, a, func as handler)
local _ref, a, t, f
script
prop fn: func
prop t : _nsstring_ from _ref
prop s : t's mutableCopy()
prop index: 0
on next()
t's rangeOfString:a options:rgex
set [j, n] to the result's [location, |length|]
if n = 0 then return the yield()
set u to (t's substringWithRange:[j, n]) as text
set c to fn(text 2 thru -1 of u)
tell s to replaceOccurrencesOfString:u ¬
withString:c options:0 |range|:[my index, ¬
|length|() - my index]
set index to index + j
set t to the substringFromIndex_(index) of s
next()
end next
on yield()
try
set _ref's contents to s as text
end try
s as text
end yield
end script
result's next()
end map
to base_10 from base_16
# There's probably a more ASObjC-y way to do this
local base_16
set p to 1
set |ξ| to 0
script hexadecimal
prop digits: "123456789ABCDEF"
prop coefficients: reverse of base_16's characters
end script
repeat with x in hexadecimal's coefficients
set |ξ| to |ξ| + (offset of x in (hexadecimal's digits)) * p
set p to p * 16
end repeat
|ξ|
end denary
to char(k)
if k's class = text then set k to (base_10 from k)
character id k
end char
---------------------------------------------------------------------------❮END❯
Основной обработчик, который вы будете вызывать, это qp_decode()
, который принимает единственный аргумент, который может быть литеральной строкой или путем к файлу, при котором содержимое файла читается и обрабатывается в виде строки в кодировке UTF-8, а затем обрабатывается как строковый аргумент.
Я отмечаю в ветке комментариев, что вы используете Script Debugger . Если сценарий не удается скомпилировать или выполнить, я бы порекомендовал запустить сценарий в Редактор сценариев (однако здесь вам нужно будет снова скопировать / вставить из исходного источника, как Отладчик сценариев манипулирует содержимым буфера обмена перед вставкой). Я на самом деле использовал vim
и osascript
при разработке и отладке этого скрипта, так что это девственный текст.