Пример A-20. Функции для работы со строками

Пример A-20. Функции для работы со строками

  1. #!/bin/bash
  2. # string.bash --- эмуляция библиотеки функций string(3)
  3. # Автор: Noah Friedman <friedman@prep.ai.mit.edu>
  4. # ==>     Используется с его разрешения.
  5. # Дата создания: 1992-07-01
  6. # Дата последней модификации: 1993-09-29
  7. # Public domain
  8. # Преобразование в синтаксис bash v2 выполнил Chet Ramey
  9. # Комментарий:
  10. # Код:
  11. #:docstring strcat:
  12. # Порядок использования: strcat s1 s2
  13. #
  14. # Strcat добавляет содержимое переменной s2 к переменной s1.
  15. #
  16. # Пример:
  17. #    a="foo"
  18. #    b="bar"
  19. #    strcat a b
  20. #    echo $a
  21. #    => foobar
  22. #
  23. #:end docstring:
  24. ###;;;autoload
  25. function strcat ()
  26. {
  27.     local s1_val s2_val
  28.     s1_val=${!1}                        # косвенная ссылка
  29.     s2_val=${!2}
  30.     eval "$1"=\'"${s1_val}${s2_val}"\'
  31.     # ==> eval $1='${s1_val}${s2_val}' во избежание проблем,
  32.     # ==> если одна из переменных содержит одиночную кавычку.
  33. }
  34. #:docstring strncat:
  35. # Порядок использования: strncat s1 s2 $n
  36. #
  37. # Аналог strcat, но добавляет не более n символов из
  38. # переменной s2. Результат выводится на stdout.
  39. #
  40. # Пример:
  41. #    a=foo
  42. #    b=barbaz
  43. #    strncat a b 3
  44. #    echo $a
  45. #    => foobar
  46. #
  47. #:end docstring:
  48. ###;;;autoload
  49. function strncat ()
  50. {
  51.     local s1="$1"
  52.     local s2="$2"
  53.     local -i n="$3"
  54.     local s1_val s2_val
  55.     s1_val=${!s1}                       # ==> косвенная ссылка
  56.     s2_val=${!s2}
  57.     if [ ${#s2_val} -gt ${n} ]; then
  58.        s2_val=${s2_val:0:$n}            # ==> выделение подстроки
  59.     fi
  60.     eval "$s1"=\'"${s1_val}${s2_val}"\'
  61.     # ==> eval $1='${s1_val}${s2_val}' во избежание проблем,
  62.     # ==> если одна из переменных содержит одиночную кавычку.
  63. }
  64. #:docstring strcmp:
  65. # Порядок использования: strcmp $s1 $s2
  66. #
  67. # Strcmp сравнивает две строки и возвращает число меньше, равно
  68. # или больше нуля, в зависимости от результатов сравнения.
  69. #:end docstring:
  70. ###;;;autoload
  71. function strcmp ()
  72. {
  73.     [ "$1" = "$2" ] && return 0
  74.     [ "${1}" '<' "${2}" ] > /dev/null && return -1
  75.     return 1
  76. }
  77. #:docstring strncmp:
  78. # Порядок использования: strncmp $s1 $s2 $n
  79. #
  80. # Подобна strcmp, но сравнивает не более n символов
  81. #:end docstring:
  82. ###;;;autoload
  83. function strncmp ()
  84. {
  85.     if [ -z "${3}" -o "${3}" -le "0" ]; then
  86.        return 0
  87.     fi
  88.     if [ ${3} -ge ${#1} -a ${3} -ge ${#2} ]; then
  89.        strcmp "$1" "$2"
  90.        return $?
  91.     else
  92.        s1=${1:0:$3}
  93.        s2=${2:0:$3}
  94.        strcmp $s1 $s2
  95.        return $?
  96.     fi
  97. }
  98. #:docstring strlen:
  99. # Порядок использования: strlen s
  100. #
  101. # возвращает количество символов в строке s.
  102. #:end docstring:
  103. ###;;;autoload
  104. function strlen ()
  105. {
  106.     eval echo "\${#${1}}"
  107.     # ==> Возвращает длину переменной,
  108.     # ==> чье имя передается как аргумент.
  109. }
  110. #:docstring strspn:
  111. # Порядок использования: strspn $s1 $s2
  112. #
  113. # Strspn возвращает максимальную длину сегмента в строке s1,
  114. # который полностью состоит из символов строки s2.
  115. #:end docstring:
  116. ###;;;autoload
  117. function strspn ()
  118. {
  119.     # Сброс содержимого переменной IFS позволяет обрабатывать пробелы как обычные символы.
  120.     local IFS=
  121.     local result="${1%%[!${2}]*}"
  122.     echo ${#result}
  123. }
  124. #:docstring strcspn:
  125. # Порядок использования: strcspn $s1 $s2
  126. #
  127. # Strcspn возвращает максимальную длину сегмента в строке s1,
  128. # который полностью не содержит символы из строки s2.
  129. #:end docstring:
  130. ###;;;autoload
  131. function strcspn ()
  132. {
  133.     # Сброс содержимого переменной IFS позволяет обрабатывать пробелы как обычные символы.
  134.     local IFS=
  135.     local result="${1%%[${2}]*}"
  136.     echo ${#result}
  137. }
  138. #:docstring strstr:
  139. # Порядок использования: strstr s1 s2
  140. #
  141. # Strstr выводит подстроку первого вхождения строки s2
  142. # в строке s1, или ничего не выводит, если подстрока s2 в строке s1 не найдена.
  143. # Если s2 содержит строку нулевой длины, то strstr выводит строку s1.
  144. #:end docstring:
  145. ###;;;autoload
  146. function strstr ()
  147. {
  148.     # Если s2 — строка нулевой длины, то вывести строку s1
  149.     [ ${#2} -eq 0 ] && { echo "$1" ; return 0; }
  150.     # не выводить ничего, если s2 не найдена в s1
  151.     case "$1" in
  152.     *$2*) ;;
  153.     *) return 1;;
  154.     esac
  155.     # использовать шаблон, для удаления всех несоответствий после s2 в s1
  156.     first=${1/$2*/}
  157.     # Затем удалить все несоответствия с начала строки
  158.     echo "${1##$first}"
  159. }
  160. #:docstring strtok:
  161. # Порядок использования: strtok s1 s2
  162. #
  163. # Strtok рассматривает строку s1, как последовательность из 0, или более,
  164. # лексем (токенов), разделенных символами строки s2
  165. # При первом вызове (с непустым аргументом s1)
  166. # выводит первую лексему на stdout.
  167. # Функция запоминает свое положение в строке s1 от вызова к вызову,
  168. # так что последующие вызовы должны производиться с пустым первым аргументом,
  169. # чтобы продолжить выделение лексем из строки s1.
  170. # После вывода последней лексемы, все последующие вызовы будут выводить на stdout
  171. # пустое значение. Строка-разделитель может изменяться от вызова к вызову.
  172. #:end docstring:
  173. ###;;;autoload
  174. function strtok ()
  175. {
  176.  :
  177. }
  178. #:docstring strtrunc:
  179. # Порядок использования: strtrunc $n $s1 {$s2} {$...}
  180. #
  181. # Используется многими функциями, такими как strncmp, чтобы отсечь "лишние" символы.
  182. # Выводит первые n символов в каждой из строк s1 s2 ... на stdout.
  183. #:end docstring:
  184. ###;;;autoload
  185. function strtrunc ()
  186. {
  187.     n=$1 ; shift
  188.     for z; do
  189.         echo "${z:0:$n}"
  190.     done
  191. }
  192. # provide string
  193. # string.bash конец библиотеки
  194. # ========================================================================== #
  195. # ==> Все, что находится ниже, добавлено автором документа.
  196. # ==> Чтобы этот сценарий можно было использовать как "библиотеку", необходимо
  197. # ==> удалить все, что находится ниже и "source" этот файл в вашем сценарии.
  198. # strcat
  199. string0=one
  200. string1=two
  201. echo
  202. echo "Проверка функции \"strcat\" :"
  203. echo "Изначально \"string0\" = $string0"
  204. echo "\"string1\" = $string1"
  205. strcat string0 string1
  206. echo "Теперь \"string0\" = $string0"
  207. echo
  208. # strlen
  209. echo
  210. echo "Проверка функции  \"strlen\" :"
  211. str=123456789
  212. echo "\"str\" = $str"
  213. echo -n "Длина строки \"str\" = "
  214. strlen str
  215. echo
  216. # Упражнение:
  217. # ---------
  218. # Добавьте проверку остальных функций.
  219. exit 0