Advanced Bash-Scripting Guide: Искусство программирования на языке сценариев командной оболочки | ||
---|---|---|
Назад | Глава 9. К вопросу о переменных | Вперед |
Bash поддерживает на удивление большое количество операций над строками. К сожалению, этот раздел Bash испытывает недостаток унификации. Одни операции являются подмножеством операций подстановки параметров, а другие -- совпадают с функциональностью команды UNIX -- expr. Это приводит к противоречиям в синтаксисе команд и перекрытию функциональных возможностей, не говоря уже о возникающей путанице.
Длина строки
stringZ=abcABC123ABCabc echo ${#stringZ} # 15 echo `expr length $stringZ` # 15 echo `expr "$stringZ" : '.*'` # 15
Пример 9-10. Вставка пустых строк между параграфами в текстовом файле
#!/bin/bash # paragraph-space.sh # Вставка пустых строк между параграфами в текстовом файле. # Порядок использования: $0 <FILENAME MINLEN=45 # Возможно потребуется изменить это значение. # Строки, содержащие количество символов меньшее, чем $MINLEN #+ принимаются за последнюю строку параграфа. while read line # Построчное чтение файла от начала до конца... do echo "$line" # Вывод строки. len=${#line} if [ "$len" -lt "$MINLEN" ] then echo # Добавление пустой строки после последней строки параграфа. fi done exit 0
Длина подстроки в строке (подсчет совпадающих символов ведется с начала строки)
где $substring -- регулярное выражение.
где $substring -- регулярное выражение.
stringZ=abcABC123ABCabc # |------| echo `expr match "$stringZ" 'abc[A-Z]*.2'` # 8 echo `expr "$stringZ" : 'abc[A-Z]*.2'` # 8
Index
Номер позиции первого совпадения в $string c первым символом в $substring.
stringZ=abcABC123ABCabc echo `expr index "$stringZ" C12` # 6 # позиция символа C. echo `expr index "$stringZ" 1c` # 3 # символ 'c' (в #3 позиции) совпал раньше, чем '1'.
Эта функция довольно близка к функции strchr() в языке C.
Извлечение подстроки
Извлекает подстроку из $string, начиная с позиции $position.
Если строка $string -- "*" или "@", то извлекается позиционный параметр (аргумент), [1] с номером $position.
Извлекает $length символов из $string, начиная с позиции $position.
stringZ=abcABC123ABCabc # 0123456789..... # Индексация начинается с 0. echo ${stringZ:0} # abcABC123ABCabc echo ${stringZ:1} # bcABC123ABCabc echo ${stringZ:7} # 23ABCabc echo ${stringZ:7:3} # 23A # Извлекает 3 символа. # Возможна ли индексация с "правой" стороны строки? echo ${stringZ:-4} # abcABC123ABCabc # По-умолчанию выводится полная строка. # Однако . . . echo ${stringZ:(-4)} # Cabc echo ${stringZ: -4} # Cabc # Теперь выводится правильно. # Круглые скобки или дополнительный пробел "экранируют" параметр позиции. # Спасибо Dan Jacobson, за разъяснения.
Если $string -- "*" или "@", то извлекается до $length позиционных параметров (аргументов), начиная с $position.
echo ${*:2} # Вывод 2-го и последующих аргументов. echo ${@:2} # То же самое. echo ${*:2:3} # Вывод 3-х аргументов, начиная со 2-го.
Извлекает $length символов из $string, начиная с позиции $position.
stringZ=abcABC123ABCabc # 123456789...... # Индексация начинается с 1. echo `expr substr $stringZ 1 2` # ab echo `expr substr $stringZ 4 3` # ABC
Находит и извлекает первое совпадение $substring в $string, где $substring -- это регулярное выражение.
Находит и извлекает первое совпадение $substring в $string, где $substring -- это регулярное выражение.
stringZ=abcABC123ABCabc # ======= echo `expr match "$stringZ" '\(.[b-c]*[A-Z]..[0-9]\)'` # abcABC1 echo `expr "$stringZ" : '\(.[b-c]*[A-Z]..[0-9]\)'` # abcABC1 echo `expr "$stringZ" : '\(.......\)'` # abcABC1 # Все вышеприведенные операции дают один и тот же результат.
Находит и извлекает первое совпадение $substring в $string, где $substring -- это регулярное выражение. Поиск начинается с конца $string.
Находит и извлекает первое совпадение $substring в $string, где $substring -- это регулярное выражение. Поиск начинается с конца $string.
stringZ=abcABC123ABCabc # ====== echo `expr match "$stringZ" '.*\([A-C][A-C][A-C][a-c]*\)'` # ABCabc echo `expr "$stringZ" : '.*\(......\)'` # ABCabc
Удаление части строки
Удаление самой короткой, из найденных, подстроки $substring в строке $string. Поиск ведется с начала строки
Удаление самой длинной, из найденных, подстроки $substring в строке $string. Поиск ведется с начала строки
stringZ=abcABC123ABCabc # |----| # |----------| echo ${stringZ#a*C} # 123ABCabc # Удаление самой короткой подстроки. echo ${stringZ##a*C} # abc # Удаление самой длинной подстроки.
Удаление самой короткой, из найденных, подстроки $substring в строке $string. Поиск ведется с конца строки
Удаление самой длинной, из найденных, подстроки $substring в строке $string. Поиск ведется с конца строки
stringZ=abcABC123ABCabc # || # |------------| echo ${stringZ%b*c} # abcABC123ABCa # Удаляется самое короткое совпадение. Поиск ведется с конца $stringZ. echo ${stringZ%%b*c} # a # Удаляется самое длинное совпадение. Поиск ведется с конца $stringZ.
Пример 9-11. Преобразование графических файлов из одного формата в другой, с изменением имени файла
#!/bin/bash # cvt.sh: # Преобразование всех файлов в заданном каталоге, #+ из графического формата MacPaint, в формат "pbm". # Используется утилита "macptopbm", входящая в состав пакета "netpbm", #+ который сопровождается Brian Henderson (bryanh@giraffe-data.com). # Netpbm -- стандартный пакет для большинства дистрибутивов Linux. OPERATION=macptopbm SUFFIX=pbm # Новое расширение файла. if [ -n "$1" ] then directory=$1 # Если каталог задан в командной строке при вызове сценария else directory=$PWD # Иначе просматривается текущий каталог. fi # Все файлы в каталоге, имеющие расширение ".mac", считаются файлами #+ формата MacPaint. for file in $directory/* # Подстановка имен файлов. do filename=${file%.*c} # Удалить расширение ".mac" из имени файла #+ ( с шаблоном '.*c' совпадают все подстроки #+ начинающиеся с '.' и заканчивающиеся 'c', $OPERATION $file > "$filename.$SUFFIX" # Преобразование с перенаправлением в файл с новым именем rm -f $file # Удаление оригинального файла после преобразования. echo "$filename.$SUFFIX" # Вывод на stdout. done exit 0 # Упражнение: # -------- # Сейчас этот сценарий конвертирует *все* файлы в каталоге # Измените его так, чтобы он конвертировал *только* те файлы, #+ которые имеют расширение ".mac".
Замена подстроки
Замещает первое вхождение $substring строкой $replacement.
Замещает все вхождения $substring строкой $replacement.
stringZ=abcABC123ABCabc echo ${stringZ/abc/xyz} # xyzABC123ABCabc # Замена первой подстроки 'abc' строкой 'xyz'. echo ${stringZ//abc/xyz} # xyzABC123ABCxyz # Замена всех подстрок 'abc' строкой 'xyz'.
Подстановка строки $replacement вместо $substring. Поиск ведется с начала строки $string.
Подстановка строки $replacement вместо $substring. Поиск ведется с конца строки $string.
stringZ=abcABC123ABCabc echo ${stringZ/#abc/XYZ} # XYZABC123ABCabc # Поиск ведется с начала строки echo ${stringZ/%abc/XYZ} # abcABC123ABCXYZ # Поиск ведется с конца строки
В качестве альтернативы, Bash-скрипты могут использовать средства awk при работе со строками.
Пример 9-12. Альтернативный способ извлечения подстрок
#!/bin/bash # substring-extraction.sh String=23skidoo1 # 012345678 Bash # 123456789 awk # Обратите внимание на различия в индексации: # Bash начинает индексацию с '0'. # Awk начинает индексацию с '1'. echo ${String:2:4} # с 3 позиции (0-1-2), 4 символа # skid # В эквивалент в awk: substr(string,pos,length). echo | awk ' { print substr("'"${String}"'",3,4) # skid } ' # Передача пустого "echo" по каналу в awk, означает фиктивный ввод, #+ делая, тем самым, ненужным предоставление имени файла. exit 0
Дополнительную информацию, по работе со строками, вы найдете в разделе Section 9.3 и в секции, посвященной команде expr. Примеры сценариев:
[1] |
Применяется к аргументам командной строки или входным параметрам функций. |