Похоже, что pdfencrypt
требует 8-битный (пароль в кодировке ISO -8859 )и не знает, как обращаться с (, т.е. преобразовывать )UTF -8 паролей.
Вы должны использовать совместимую кодировку символов при выполнении pdfencrypt
, для шифрования и дешифрования. Обычный ASCII ("C" )или ISO -8859 -n (, например "de _DE.latin1", как предложил Хауке Лагинг ), должен работать. На мой взгляд, это просто указывает pdfencrypt
принимать символы вашего пароля как есть (, т.е. не требуется преобразования ), вот и все.
Просто добавьте эту строку вверху скрипта:
export LC_ALL=de_DE.latin1 # Or fr_FR, or latin15, or... Any valid locale for your system
Или может быть достаточно изменить эту единственную строку:
LC_ALL=de_DE.latin1 pdfencrypt "$1" -p "$password" -o "$2"
Сделайте то же самое для декодирования.
Если вы преобразуете свой пароль с помощью iconv
вместо установки LC _ALL, я думаю, у вас будет та же проблема, поскольку pdfencrypt
все еще будет полагать, что вы даете ему UTF -8 символов, когда он встречает 8 бит те.
В любом случае, чтобы упростить задачу, вам, вероятно, следует придерживаться 7-битного набора символов ASCII :, пробела, букв без -акцента, цифр, основных знаков препинания и т. д.(man 7 ascii
)
Что касается пробела, вы должны знать, что чтение в определенную переменную с помощью(read -r var
)удаляет начальные и конечные пробелы (фактически символы в переменной оболочкиIFS
). Это может раздражать для пароля. Вы должны использовать read -r
, чтобы поместить всю прочитанную строку в переменную REPLY
.
Это дало бы этот код:
export LC_ALL=de_DE.latin1
read -r -s -p "Password: "
echo
pdfencrypt "$1" -p "$REPLY" -o "$2"
$ awk -v OFS='\t' '/^bindsym/ { key = $2; sub(".*#", ""); print key, $0 }' file
$mod+F2 Open terminal
$mod+p Popup Dictionary
$mod+Mod1+l Dmenu for my books collection
Mod1+Control+b nnn file browser
Здесь используется awk
для извлечения второго поля в каждой строке, начинающейся с bindsym
, в переменную key
. Затем он удаляет все до #
включительно в строке и печатает key
и оставшуюся часть строки с табуляцией в качестве разделителя.
Альтернативное форматирование вывода:
$ awk '/^bindsym/ { key = $2; sub(".*#", ""); printf("%-20s\t%-20s\n", key, $0) }' file
$mod+F2 Open terminal
$mod+p Popup Dictionary
$mod+Mod1+l Dmenu for my books collection
Mod1+Control+b nnn file browser
Логика такая же, но вывод выделяет 20 символов для каждого из двух (левых -выравниваемых )полей и помещает табуляцию в -между ними (для надежности ).
Использование функции match()
GNU awk
для сопоставления части от #
до конца строки
awk '/bindsym/ && match($0,/#(.+)$/,arr){print $2, arr[1]}' filep
Функция match()
заполняет массив, указанный в третьем аргументе, совпавшим шаблоном из регулярного выражения во втором аргументе.
в любом POSIX awk
, третий аргумент match()
— не поддерживается , а пара специальных переменных RSTART
и RLENGTH
, которые отмечают начало и длина согласованной группы. Мы используем функцию substr()
в текущей строке, чтобы получить совпадающую строку
awk '/bindsym/ && match($0,/#(.+)$/){print $2, substr($0,RSTART+1,RLENGTH)}' file
Чтобы красиво -распечатать вывод, вы можете использовать функцию printf()
, как в другом ответе.
Step1: count=`awk '{print NR}'|sed -n '$p' filename`
Step2:for ((i=1;i<=$count;i++)); do awk -v i="$i" 'NR==i && $0 ~ /^bindsym/{print $2}' filename; sed -n ""$i"s/.*#//p" filename; done| sed "N;s/\n/ /g"
output
for ((i=1;i<=$count;i++)); do awk -v i="$i" 'NR==i && $0 ~ /^bindsym/{print $2}' filename; sed -n ""$i"s/.*#//p" filename; done| sed "N;s/\n/ /g"
$mod+F2 Open terminal
$mod+p Popup Dictionary
$mod+Mod1+l Dmenu for my books collection
Mod1+Control+b nnn file browser
Это очень просто сделать в sed
; поскольку ваши данные на самом деле не ориентированы на поля, Awk не дает здесь огромных преимуществ:
sed 's/^[^ ]* //;s/.*#//' inputfile
Перевод:
s/^[^ ]* //
Удалить все до первого пробела включительно.
s/.*#//
Удалить все от первого (оставшегося )символа пробела до последнего #
символа в строке.