Утилита sed никогда не используется в одиночку, её использование очень тесно связано с использованием оболочки. Я использую bash, и потому про эту оболочку также стоит сказать несколько слов.
К счастью, про bash уже многое написано, вы можете почитать man bash, а если вам этого недостаточно, то и info bash. Кроме того, имеется Advanced Bash Scripting (сокращённо - ABS), в котором расписаны многие тонкие моменты кодинга на этом ЯП.
Тем не менее, даже в ABS некоторые моменты не раскрыты. Это и заставило меня написать данное руководство.
Прежде всего, стоит заметить, что утилита bash на самом деле обрабатывает текстовый поток. Причём построчно (как и sed), разбор каждой загруженной строки прост:
$ echo -e "$IFS" | hexdump -c 0000000 \t \n \n 0000004Эта команда вывела нам список разделителей - как видно, у меня установлено три разделителя, это пробел, табуляция и перевод строки (вообще-то переводов строки 2 шт, второй был добавлен командой echo).
./my_scriptКонечно при этом необходимо установить право исполнения для этого файла, командой
chmod +x my_script
Следует учитывать, что файлы ВСЕГДА создаются со сброшенным правом исполнения. Это тоже связано с безопасностью: злоумышленник не сможет нас заставить выполнить свою команду, если мы только явно не пропишем право её исполнения.
Если вы хотите ещё большей защиты, то вы можете монтировать раздел /home с опцией noexec, это приведёт к тому, что НИКТО не сможет выполнить файлы в данном разделе (а создание файлов во всех прочих разделах запрещено. Конечно необходимо запретить создание исполняемых файлов в общедоступных директориях /tmp и /var/tmp).
Однако, не следует забывать, что любой пользователь может выполнить любой скрипт подсунув его как параметр утилите bash. Для этого права выполнения НЕ нужно. Достаточно права выполнения самой bash (которое всегда есть), и права чтения этого скрипта.
После разделения строки на слова, выполняется первое слово как команда. Все остальные слова считаются параметрами. Из bash скрипта к ним можно получить доступ с помощью конструкций $0, $1, $2 и т.д.. Все целиком можно получить конструкцией $@ (в эту конструкцию НЕ входит $0, т.е. имя самой команды).
Однако, разбор командной строки вовсе не завершается после разделения её на слова. Если в некоторых словах имеются символы *, {, }, ?, [, и ], то это слово считается именем файла.
Вместо звёздочки (*) подставляется любое количество любых файлов. К примеру, если у нас в текущем каталоге имеются файлы
1.html
2.html
3.html
То, команда xxx *.html получит не один параметр, а 3. Данная команда выполнится так-же, как если-бы мы явно записали xxx 1.html 2.html 3.html. Если файлов подходящих под шаблон нет, то команда получит сам шаблон в неизменном виде.
Звёздочка раскрывает любые файлы, кроме скрытых (скрытыми файлами и каталогами считаются любые файлы, первым символом в которых стоит точка (.)). Для вывода скрытых файлов следует использовать следующее выражение: .*. Некоторые утилиты так-же позволяют обрабатывать скрытые файлы путём указания опций
. Например, утилита ls показывает скрытые файлы с опцией -a
.
Следует помнить про 2 скрытых подкаталога, которые присутствуют в любом каталоге - это ссылка на сам каталог '.', и ссылка на родительский каталог '..'. Если вы обрабатываете скрытые файлы, вам надо учитывать эти каталоги (для избежания зацикливания скрипта).
Если вам необходимо передать в свою программу все файлы, вам следует записать xxx .* * При этом первое выражение (.*) раскроется во все скрытые файлы и каталоги, а второе - будет заменено на все обычные файлы.
Конечно, если у вас нет в этом каталоге обычных файлов (скрытые файлы всегда есть, это '.' и '..'), то вторая звёздочка не раскроется, и будет передана утилите xxx без изменений. На что она может выругаться, типа «Нет такого файла '*'».
xxx *.mp3Именно по этой причине, я и рекомендую задавать всем файлам осмысленные расширения - да, они не нужны для ОС (в отличие от M$-DOS), однако очень помогут нам.
В отличие от одиночной звёздочки (которая раскрывается в список файлов), двойная звёздочка раскрывается в список каталогов. К примеру, xxx **/*.sed приведёт к тому, что в утилиту xxx передадутся имена всех sed-скриптов во всех подкаталогах текущего каталога. При этом sed-скрипты из текущего каталога НЕ будут переданы в эту утилиту.
Кроме того, файлы из подкаталогов в подкаталогах так-же не будут переданы. Действие двойной звёздочки аналогично команде find -maxdepth 2 -mindepth 2, только двойная звёздочка ещё и сортирует файлы и не показывает скрытые каталоги.
xxx *.[jJ][pP][gG]оно совпадает и с файлами вроде 1.jpg, и с 1.JPG, т.е. является регистронезависимым. Диапазоны так-же допускаются, к примеру
xxx *.[0-9]расширяется в любые файлы, которые имеют расширения из любой цифры.
xxx *.[0-9] *.[0-9][0-9] *.[0-9][0-9][0-9]
Команды в bash обычно принимают параметры из стандартного потока ввода (/dev/stdin) и отправляют результат своей работы в стандартный поток вывода (/dev/stdout).
Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).
Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.