Сейчас на форуме: rmn, asfa, surunnerr, Vicshann (+4 невидимых)

 eXeL@B —› Оффтоп —› вопросы по shell.
Посл.ответ Сообщение

Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 31 марта 2008 06:44 · Поправил: Small_S
· Личное сообщение · #1

Привет всем. Суть проблемы в следующем. Идет сессия, по предмету "Операционные системы.", подвисает
последняя контрольная. И вроде ничего мудреного, но что то недопру никак. Суть задания - создать
скрипт в среде эмулятора системы UNIX- Cygwin, который бы в заданном каталоге у всех txt файлов
создавал или менял(если она есть) первую строку файла на строку вводимую пользователем(желательно запуск с этими параметрами из командной строки). Пока упрощенный скрипт(последовательный ввод по приглашению) я создал только он почему то обрабатывает 2 файла и всё. Судя по пустому репорту обнаруженных файлов цикл отрабатывает полностью, а вот действия по вводу в каждый заголовок строки происходят не полностью(2раза).Скрипт имеет вид:

echo Введите путь к каталогу в котором будут меняться заголовки файлов.
read x; echo В каталоге обнаружены следующие файлы; find $x -type f -a -name '*.txt' > report.txt
echo $( < report.txt); echo Введите новый заголовок этих файлов.; read y
ostatok=5;
while [ -n "$ostatok" ]
do
read imia ostatok < report.txt
ostatok=$(sed report.txt -e {"1 d"})
echo $imia
echo $y > $imia
echo $ostatok > report.txt
done

Запускаю пока просто sh ren_contr(он без командных парам.).
Действия понятны, но всё равно поясню.

1 -приглашение ввести каталог
2 -конвейер -->ввод пути каталога --> вывод сообщения о списке обнаруженных файлов --> сам поиск с записью репорт
3 -конвейер -->выводим из репорта список на экран --> приглашаем ввести заголовок --> сам ввод заголовка
4 -переменная для цикла(не ноль)
5 -начало цикла
6 -вводим из репорта в imia- первое слово в ostatok- второе слово(на данном этапе оно пустое- окончание строки
так как путь с именем файла идёт как непрерывное слово и всё забирает переменная imia.
7 -присваиваем новое значение переменной ostatok после обрезки в sed-е первой строки.
8 -это просто для контроля выводим на экран
9 -наконец вносим заголовок на место в находящийся в переменной imia файл.
10 -а переменную ostatok c оставшимися файлами скидываем назад в репорт

Цикл крутиться пока в репорте не исчезнет последняя запись. Вроде всё логично и выполняется,но...
Может кто подскажет в чем дело, ну и другие варианты приветствуются, я пробовал тоже через sed заголовок писать в файлы в строке 9, но видимо косячу с синтаксисом, что то не получается.

И ещё по ходу вопросы из которых главный нет ли отладчика под shell-ом чтобы посмотреть что происходит с переменными, методичка молчит, в гугле при описании скриптового языка не встречаю. Скрипты тоже искал в гугле, но на мою тему нет или не попалось. И вообще язык этот после асма и делфей, да даже после васика, смотрится как то убого, синтаксис-жесть. Текст и так может быть выражен,и так,и эдак, и вот вот так. В чём кайф не въеду. И вот эти задания в наших контрольных с
работой с текстами ну так сочетаются с его возможностями( в sed поболее можно, но там ещё свой синтаксис сам чёрт ногу сломит пока их подружишь) просто вау. Если ещё учесть, что команды при выполнении скрипта можно брать только с двух методических пособий(а там кое чего нет), то картина станет полной.



Ранг: 310.8 (мудрец), 29thx
Активность: 0.430
Статус: Участник

Создано: 31 марта 2008 09:32
· Личное сообщение · #2

1) команда echo $y > $imia заменит все содержимое, а не только первую строку
2) конструкция ostatok=$(sed report.txt -e {"1 d"}) приводит к тому, что убираются
все символы конца строки и при втором исполнении в report.txt ничего не остается
3) для отладки можно использовать какой-то ключ при вызове sh - будет выдаваться
протокол выполнения , либо просто выдавать на консоль содержимое переменных
и файлов, чтобы убедится, что все работает так как ты задумал. Именно так я и определил,
что записывется в переменную ostatok.



Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 31 марта 2008 17:21
· Личное сообщение · #3

tundra37 большое человеческое спс. А то я уже в затуп от перенапряжения вхожу, вот и не сообразил как бы переменную глянуть.

Однако теперь другой затык -сразу за структурой ostatok=$(sed report.txt -e {"1 d"}) пытаюсь восстановить возврат каретки(или как больше нравиться концы строк), делаю так как увидел на одном сайте там пример

chrish@dhcp3 [345]$ echo -e 'hello\tthere'
hello there
chrish@dhcp3 [346]$ echo -e 'hello\tthere' | sed -e 's/[[:space:]]/, /'
hello, there

Моя конструкция которую принимает мой sed выглядит так:

sed report.txt -e 's\[[:space:]]\[[:\r:]]\g'

Двойной слеш там для экранирования как у меня для седа в методичках пишут.
Млинн, спейс этот хренов sed махом меняет на всё что угодно только не на возврат каретки, с любым количеством скобок или с экранированием или без. Ему фиолетово,- команда s, которая исправно меняла всё чо хочешь сразу становится седу незнакомой(типа неизвестная операция 's').
Уж каким раком, боком я это \r или \015 или \x00D или даже Enter(хрен их придурков-разработчиков этого чуда-юда знает) не ставил. Всё без толку.

Жена предлагает новопассит, но это не выход.

Кто нибудь знает как возврат каретки символом в херовом sed-е задаётся?
И ещё есть ли способ в shell-е как в делфях или нормальных скриптовых языках(типа олидбгскрипте) асм-вставки вставлять?


Я заранее прошу прощения за весьма агрессивный пост у модераторов, но просто уже колотит от мысли, что за два дня хелоу ворлд не могу в пять шесть txt-шек написать программно.




Ранг: 467.7 (мудрец), 5thx
Активность: 0.270
Статус: Участник
Иной :)

Создано: 01 апреля 2008 18:19 · Поправил: [HEX]
· Личное сообщение · #4

Small_S
В цикл с подстановкой найденых файлов думаю сам засунешь.
#!/bin/sh
read y
sed -e "1d" $1 >$1.tmp
newline="$y\
"
echo $newline >$1.new
cat $1.tmp >>$1.new
rm -f $1.tmp


Не шикарный метод конечно, но всеже рабочий.

-----
Computer Security Laboratory




Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 01 апреля 2008 21:57
· Личное сообщение · #5

[HEX] спс. завтра буду пробовать, уже сил нет $1-это так понимаю то где у меня найденные файлы были(report.txt) после find-а.

Походу там с этой кареткой какой то цирк. Думал это sed из-за мудрёного синтаксиса-экранирования не всасывает, но вот попробовал tr [[:space:]] [[:\r:]] < $ostatok так тоже нивкакую теперь уже шеловая команда tr пробел видит а возврат каретки нет и как в седе меняет пробел на что хочеш только не на каретку. Тоже и экранировать по всякому пробовал, и так, и эдак, всякие слешики, кавычечки, скобочки, метасимволы ему полный фиолет, не, мягко выразился,- ультрафиолет. Всё это чудо, слышал как то, на си писалось тем более непонятно чего оно \r не всасывает(этож вроде сишное обозначение изначально)

Не, помимо выполнения контрольной жутко интересно зачем так набаламутили с синтаксисом разработчики этож мешает кодингу. И команды тоже тяп ляп- она должна отрезать строку по указанному номеру, так строку режет и ещё удаляет каретку какого то(ну это хоть ленью можно обьяснить). А вот синтаксические изыски садо-мазо какое то. Или я в какойто запредельный, недоступный простым смертным кайф не въеду.



Ранг: 72.7 (постоянный)
Активность: 0.080
Статус: Участник

Создано: 05 апреля 2008 10:07
· Личное сообщение · #6

Привет всем. Наконец прикончил задание. Млин пришлось ещё пару дней убить. В скрипт пришлось вносить второй цикл чтобы справиться с багом по удалению возврата каретки. С тем, что дал [HEX] разобрался, но уточнив у препода не стал туда вносить и мучиться совмещать(так как это чтобы строки старые не терялись, а смещались в конец под новый заголовок). Вот скрипт с внесением пути каталога и добавляемого заголовка из командной строки. Запускается стандартно:
sh script2 <каталог где будем менять> <заголовок который вносим>

Скрипт выглядит так(немного меняю для лучшего понимания):

echo Введённый путь к каталогу в котором будут переименовываться файлы.
x=$1; echo $x
echo В каталоге обнаружены следующие файлы
find $x -type f -a -name '*.txt' > report
echo $( < report )
echo Введённый новый заголовок этих файлов.; y=$2; echo $y;
ostatok=5
while [ -n "$ostatok" ]
do
read imia ostatok < report
echo $ostatok; echo $ostatok > report2
ostatok=$(sed report -e {"1 d"})
echo $ostatok > report
echo $y > $imia
done
ostatok2=5;
while [ -n "$ostatok2" ]
do
read imia2 ostatok2 < report2
echo $ostatok2
echo $ostatok2 > report2
echo $y > $imia2
done

Итак построчно выполняются действия:
1. Выводится надпись – сообщение о каталоге который ввели из командной строки.
2. Конвейер присваивает переменной x значение строки каталога и выводит его на экран.
3. Выводится надпись об списке обнаруженных файлов txt.
4. Осуществляется поиск файлов txt и помещение их списка в файл report.
5. Выводим список из файла report на экран.
6. Выводится сообщение о введённом в командной строке заголовке, переменной y присваивается значение из командной строки, это значение выводится на экран.
7. Переменная ostatok делается не равной нулю(на ней будет основан цикл).
8. Сообщаем циклу условие на работу – работаем пока ostatok не ноль.
9. Начало цикла.
10. Читаем из файла репорт в imia –первое слово(там путь первого файла), а в ostatok всё остальное.
11. Выводим значение остатка на экран(я оставил для наглядности эту отладочную информацию) .
Далее скидываем ostatok в report2 так как сед ведёт себя на следующей команде неадекватно и при
втором прогоне в переменной ostatok ничего не будет, а вся оставшаяся строка не имея символов возврата каретки уйдёт в imia.
12. Присваиваем переменной ostatok значение из файла report вырезав оттуда первую строку(предварительно sed-ом).
13. Скидываем новое содержимое из переменной ostatok назад в файл report.
14. Пишем требуемый заголовок в файл(имя и путь которого в переменной imia).
15. Коней цикла.
16. Инициализируем переменную ostatok2(делаем её не равной нулю) для второго цикла. Он нужен для того чтобы обойти баг с удалением символа возврата каретки,- иначе заголовок будет снесён в два первых по алфавиту файла.
17. Задаем условие работы второго цикла, он будет работать пока не равна нулю переменная ostatok2.
18. Начало цикла.
19. Вносим в переменную imia2 путь и имя файла в виде первого слова, а в переменную ostatok2 остальное из сохранённого ранее report2.
20. Оставил отладочный вывод значения ostatok2 на экран.
21. Пишем то, что осталось в ostatok2 назад в report2.
22. Наконец записываем по находящемуся в переменой imia2 адресу файл необходимый заголовок.
23. конец второго цикла.

Но в этом скрипте есть еще серьезный недостаток,- из командной строки можно внести в заголовок только 1 слово на английском. Ниже первый вариант скрипта в режиме диалога с пользователем. Его запускаем без параметров типа так sh script1.

echo Введите путь к каталогу в котором будут переименовываться файлы.
read x; echo В каталоге обнаружены следующие файлы; find $x -type f -a -name '*.txt' > report
echo $( < report ); echo Введите новый заголовок этих файлов.; read y
ostatok=5;
while [ -n "$ostatok" ]
do
read imia ostatok < report; echo $ostatok; echo $ostatok > report2;
ostatok=$(sed report -e {"1 d"})
echo $ostatok > report
echo $y > $imia
done; ostatok2=5;
while [ -n "$ostatok2" ]
do
read imia2 ostatok2 < report2; echo $ostatok2; echo $ostatok2 > report2;
echo $y > $imia2
done

В данном варианте можно вносить хоть предложение на русском или английском. Уф с этим предметом всё.
Всем спасибо, но закрывать топик не буду. Может ещё у кого вопросы возникнут по shell и всем миром можно будет их решить.


 eXeL@B —› Оффтоп —› вопросы по shell.

У вас должно быть 20 пунктов ранга, чтобы оставлять сообщения в этом подфоруме, но у вас только 0

   Для печати Для печати