Вы можете использовать библиотеку Python. В моей системе Fedora я сделал:
sudo dnf search bcrypt
(sudo предназначен только для того, чтобы не тратить впустую место для пользовательского кеша dnf), и из результата можно увидеть, что есть пакет Python2 и Python3:
py-bcrypt.x86_64 : Python bindings for OpenBSD's Blowfish password hashing code
python3-py-bcrypt.x86_64 : Python 3 bindings for OpenBSD's Blowfish password hashing code
Установите версию Python2 и перечислите файлы в пакете:
sudo dnf install py-bcrypt.x86_64
rpm -ql py-bcrypt.x86_64
Это показывает, что есть файл /usr/lib64/python2.7/site-packages/bcrypt / __ init __. py
, поэтому я могу получить документацию с помощью
pydoc bcrypt
Это показывает мне достаточно, чтобы написать следующую команду, которая будет хешировать строку "пароль"
:
$ python -c 'import bcrypt; print(bcrypt.hashpw("password", bcrypt.gensalt(log_rounds=10)))'
$2a$10$vWFRZgbOx6RKOKYxCTtyWuMJM60E90Vdm/.0nj.X/o3dYUxvQ/2Dm
Для более поздних версий bcrypt
используйте rounds =
вместо log_rounds =
.
$ awk 'FNR==NR { id[$1]=$2; next } { split($1,a,":"); if (a[1] in id) $1=id[a[1]]; print }' fileA fileB
>g01 [PCC6803]
ABCDEFGHIJKLMNOPQRST
>g02 [PCC6803]
UVWXYZABCDEFGHIJKLMN
>g03 [PCC6803]
OPQRSTUVWXYZABCDEFGH
Первый блок будет запущен только при чтении из первого файла(fileA
). Он считывает сопоставления строк s*
со строками >g*
в ассоциативный массив id
со строками s*
в качестве ключей.
Второй блок будет запущен только при чтении из второго файла(fileB
). Он разделит первое поле каждой строки на :
на временный массив a
. Если первый элемент результата разделения является ключом в массиве id
, все первое поле заменяется значением для этого ключа. Затем печатается возможно измененная строка.
FNR
— это номер строки, (на самом деле номер записи, но записи по умолчанию — это строки )текущего файла , а NR
— это общий номер строки. Следовательно, если FNR==NR
мы читаем из первого файла.
Ваша команда sed
почти верна. Вы определили массив с именем replacements
, но в цикле for
вы используете replacement
. Вот почему это не работает. Кроме того, вы хотите заменить всю строку до первого пробела, а не только s/$original/$new/
. Этот должен делать то, что вы хотите:
replacements=(
s12:\>g01
s16:\>g02
s48:\>g03
s52:\>g04
s80:\>g05
s81:\>g06
s87:\>g07
s91:\>g08
s92:\>g09
s93:\>g10
s94:\>g11
s96:\>g12
s97:\>g13
s98:\>g14
s99:\>g15
s100:\>g16
)
for row in "${replacements[@]}"; do
original="$(echo $row | cut -d: -f1)";
new="$(echo $row | cut -d: -f2)";
sed -i -e "s/^${original}:[^ ]*/${new}/g" FileB;
done
Это не очень эффективный способ сделать это, так как вам нужно обрабатывать весь файл B для каждой замены. Более быстрый способ может быть:
$ awk 'NR==FNR{a[$1]=$2; next}{split($1, b, /:/); if(b[1] in a){$1=a[b[1]]}}1;' FileA FileB
>g01 [PCC6803]
ABCDEFGHIJKLMNOPQRST
>g02 [PCC6803]
UVWXYZABCDEFGHIJKLMN
>g03 [PCC6803]
OPQRSTUVWXYZABCDEFGH
И внести изменения для нескольких имен файлов:
awk 'NR==FNR{
a[$1]=$2;
next
}
{
split($1, b, /:/);
if(b[1] in a){
$1=a[b[1]]
};
print > FILENAME".fixed"
}' FileA FileB FileC FileD... FileN
Это создаст fileB.fixed
, fileC.fixed
, fileD.fixed
и т. д. до FileN.fixed
. Если вы удовлетворены тем, что это сработало, вы можете затем переименовать их обратно в исходное имя файла (, предполагая, что у вас есть переименование perl -, которое используется по умолчанию в Ubuntu и Debian ):
rename 's/fixed//' *fixed
Или, если у вас нетperl-rename
:
for f in *fixed; do mv -- "$f" "${f%%.fixed}"; done
Один метод заключается в использовании sed
для формирования команд s///
из содержимого fileA
для выполнения операций с содержимым fileB
.
$ sed -Ee 's/(.*) (>.*)/s|^\1:\\S+|\2|;t/' fileA | sed -Ef - fileB
Выход:
>g01 [PCC6803]
ABCDEFGHIJKLMNOPQRST
>g02 [PCC6803]
UVWXYZABCDEFGHIJKLMN
>g03 [PCC6803]
OPQRSTUVWXYZABCDEFGH
Пояснение:
Давайте посмотрим на проблему с обратной стороны, а именно на изменение файла B. Теперь, как будет выглядеть ваша команда sed для редактирования первой строки файла B?
s/^s12:\S+/>g01/
и тогда вы закончите с этой строкой. поэтому вы помечаете пустую строку t
, чтобы сообщить sed, что для этой строки больше не требуется правок. s/(.*) (>.*)/s|^\1:\\S+|\2|;t/
s/(.*) (>.*)/
является левой частью команды замены sed и представляет собой регулярное выражение, в котором мы захватываем и сохраняем два поля в любой заданной строке файла A, например, s12 >g01
Итак, \1
должен хранить s12
и \2
должен хранить >g01
. Конечно, невысказанным предположением здесь является то, что строки содержат ровно 2 поля с одним пробелом, без начальных пробелов, а 2-е поле начинается с большего -, чем символ >
. s12 >g01
преобразуется в s|^s12:\S+|>g01|;t
на основе правой стороны команды sed. эта преобразованная строка затем применяется к файлу B, и мы получаем наши результаты. Это можно сделать, используя только один вызов GNU sed. Вместо FileB вы можете указать столько файлов, сколько у вас есть в формате FileB, но FileA должен быть указан первым. На всякий случай команда сделает резервную копию входных файлов. Если вас устраивают измененные файлы, после этого вы можете удалить резервные копии.
sed -ri.bk '1{x;s:^:cat /dev/fd/3:e;x};/:/{G;s/^([^:]+)\S+(\s+)([^\n]+).*\1\s+(>[^\n]+).*/\4\2\3/}' 3< FileA FileB
Спасибо @Stéphane Chazelas за то, что он подал мне идею использовать собственный файловый дескриптор, чтобы обойти проблему, связанную с тем, что удерживаемое пространство сбрасывается для каждого нового файла при использовании -i.