Выбрать главу
ДВА КОРОТКИХ ТРЮКА

Здесь мы покажем два коротких примера, чтобы пояснить, что мы имеем в виду. Во-первых, пользователи, заставшие Usenet, хорошо знают алгоритм rot13, помогающий сделать непристойные шуточки и оскорбления менее читаемыми. Это алгоритм подстановочного шифрования, поразительно легко реализуемый в Unix.

Чтобы что-то зашифровать по алгоритму rot13, это «что-то» нужно передать команде tr:

tr '[a-zA-Z]' '[n-za-mN-ZA-M]'

Например:

$ echo "So two people walk into a bar…" | tr '[a-zA-Z]' '[n-za-mN-ZA-M]'

Fb gjb crbcyr jnyx vagb n one…

Чтобы вернуть строке читаемый вид, достаточно применить то же преобразование:

$ echo 'Fb gjb crbcyr jnyx vagb n one…' | tr '[a-zA-Z]' '[n-za-mN-ZA-M]'

So two people walk into a bar…

Известно, что этот подстановочный шифр использовался в фильме «2001: A Space Odyssey»[7]. Помните, как там назывался компьютер? Проверим его:

$ echo HAL | tr '[a-zA-Z]' '[b-zaB-ZA]'

IBM

Другой короткий пример — проверка палиндромов. Введите что-нибудь, что на ваш взгляд является палиндромом, и этот код проверит его:

testit="$(echo $@ | sed 's/[^[: alpha: ]]//g' | tr '[: upper: ]' '[: lower: ]')"

backward="$(echo $testit | rev)"

if ["$testit" = "$backward"]; then

··echo "$@ is a palindrome"

else

··echo "$@ is not a palindrome"

fi

Палиндромом называется слово, которое одинаково читается слева направо и справа налево, поэтому первым делом код удаляет все неалфавитные символы и преобразует все буквы в нижний регистр. Затем Unix-утилита rev переворачивает задом наперед строку, полученную ею из стандартного ввода. Если прямая и перевернутая версии совпадают, значит, проверяемая строка является палиндромом; если они различаются, это не палиндром.

Показанные далее игры немногим сложнее, но все они достаточно забавны, чтобы вы добавили их в свою систему.

№ 83. Декодирование: игра в слова

Это простейшая игра в анаграммы. Если вы когда-нибудь сталкивались с подобными играми, то легко поймете суть: выбирается случайное слово, и буквы в нем переставляются случайным образом. Задача игрока — угадать исходное слово за как можно меньшее число попыток. Полный сценарий, реализующий эту игру, приводится в листинге 12.1, но, чтобы получить список слов, вам также нужно загрузить файл long-words.txt из ресурсов книги http://www.nostarch.com/wcss2/ и сохранить его в каталоге /usr/lib/games.

Код

Листинг 12.1. Игровой сценарий unscramble

··#!/bin/bash

··# unscramble — выбирает слово, кодирует его, переставляя буквы,

··#·· и предлагает пользователю угадать исходное слово (или фразу).

··wordlib="/usr/lib/games/long-words.txt"

··scrambleword()

··{

····# Выбирает случайное слово из wordlib и кодирует его.

····# Исходное слово сохраняется в $match, закодированное — в $scrambled.

····match="$(randomquote $wordlib)"

····echo "Picked out a word!"

····len=${#match}

····scrambled=""; lastval=1

····for ((val=1; $val < $len;))

····do

······if [$(($RANDOM % 2)) −eq 1]; then

········scrambled=$scrambled$(echo $match | cut −c$val)

······else

········scrambled=$(echo $match | cut −c$val)$scrambled

······fi

······val=$(($val + 1))

····done

··}

··if [! -r $wordlib]; then

····echo "$0: Missing word library $wordlib" >&2

····echo "(online: http://www.intuitive.com/wicked/examples/long-words.txt" >&2

····echo "save the file as $wordlib and you're ready to play!)" >&2

····exit 1

··fi

··newgame=""; guesses=0; correct=0; total=0

··until ["$guess" = "quit"]; do

····scrambleword

····echo ""

····echo "You need to unscramble: $scrambled"

····guess="??"; guesses=0

····total=$(($total + 1))

····while ["$guess"!= "$match" −a "$guess"!= "quit" −a "$guess"!= "next"]

····do

······echo ""

······/bin/echo −n "Your guess (quit|next): "

······read guess

······if ["$guess" = "$match"]; then

········guesses=$(($guesses + 1))

········echo ""

········echo "*** You got it with tries = ${guesses}! Well done!! ***"

········echo ""

········correct=$(($correct + 1))

······elif ["$guess" = "next" −o "$guess" = "quit"]; then

········echo "The unscrambled word was \"$match\". Your tries: $guesses"

вернуться

7

В отечественном кинопрокате вышел под названием «Космическая одиссея 2001 года». — Примеч. пер.