Как уже отмечалось, оболочка, вероятно, не лучшее место для этого. Если вы действительно хотите, вот решение с использованием awk
, dc
, printf
, sed
и tr
:
#!/bin/sh
# file: swap-bits
target_order='D5679123C4EF80AB'
indices() {
printf '%s\n' "$1" \
| sed 's/./\0 1+p\n/g' \
| sed '1s/^/10o16i/' \
| dc \
| sed 's/^/substr( $0, /' \
| sed 's/$/, 1 )/' \
| tr '\n' ' '
echo
}
sed 's/^/2o16iF/' \
| sed 's/$/p/' \
| dc \
| sed 's/....//' \
| awk "{ print \"16o2i\" $(indices ${target_order}) \"pq\" }" \
| dc \
| sed 's/^/0000/' \
| sed 's/.*\(....\)$/\1/'
Это не проверяет ввод.
Переменная target_order
должна быть установлена на предпочтительную перестановку ваших 16 бит.
Функция index
принимает в качестве входных данных такую строку и выводит последовательность команд substr ($ 0, n, 1)
, которые awk
будет использовать чтобы переставить его ввод.
Основная часть скрипта начинается с использования dc
для преобразования ввода из шестнадцатеричного в двоичный. Начальные нулевые биты сохраняются путем добавления к входу префикса F и отбрасывания четырех однобитовых. Результат передается в awk
, который печатает команду, которая сообщает dc
преобразовать двоичный код в шестнадцатеричный, затем переставленный вывод, затем команду, которая сообщает dc
напечатать и выйти. Это, конечно, подается на постоянного тока
. Наконец, снова используется sed
, чтобы убедиться, что в выходных данных присутствуют ведущие нули, если это необходимо.
Вход поступает на стандартный ввод
, вывод - на стандартный вывод
, например:
$ echo B455 | ./swap-bits
CB15
Использовать (perl )переименовать. Команда выглядит следующим образом:
rename 's/( [0-9]*).*\.ext/$1.ext/' *
Н.Б. есть два rename
, которые обычно поставляются с дистрибутивами Linux.По умолчанию обычно используется более простая версия. Переименование на основе perl -намного мощнее, потому что оно дает вам доступ к регулярным выражениям. Убедитесь, что вы используете последний. (Вы не указали свой дистрибутив, но в Arch он предоставляется пакетом perl-rename
.)
Создайте файлы (Я добавил дополнительный файл в конце ).
$ touch 'filename1 1 extra1.ext' 'filename1 2.ext' 'filename1 3 extra2.ext' 'filename2 1.ext' 'filename2 100 extra3.ext' 'filename20 1.ext' 'filename20 15 extra100.ext' 'filename3 1 3 4.ext'
Проверка команды
$ rename 's/( [0-9]*).*\.ext/$1.ext/' * -n
filename1 1 extra1.ext -> filename1 1.ext
filename1 3 extra2.ext -> filename1 3.ext
filename20 15 extra100.ext -> filename20 15.ext
filename2 100 extra3.ext -> filename2 100.ext
filename3 1 3 4.ext -> filename3 1.ext
Если вы довольны результатами, снимите флаг «пробного -запуска»/теста -n
и запустите его по-настоящему.
rename 's/foo/bar/' *
:perl rename заменит вхождение регулярного выражения foo
на bar
. Это действует на все файлы *
в текущем каталоге. Вы также можете явно заменить это на *.ext
, чтобы ограничить файлы, с которыми он работает. /( [0-9]*).*\.ext
:Совпадение с пробелом, за которым следует ряд цифр [0-9]*
, за которым следует еще один пробел. Включите первый пробел и цифры в группу захвата ( [0-9]*)
, чтобы использовать их позже. Затем сопоставьте все .*
вплоть до расширения \.ext
. Поскольку это регулярное выражение «жадное», оно попытается сопоставить как можно больше символов. т. е. если в части extra
имени файла есть цифры, окруженные пробелами, оно будет им соответствовать. /$1.ext
Замените эту совпадающую часть группой захвата сверху $1
, т. е. пробелом и цифрами, за которыми следует расширение .ext
.