LINUX.ORG.RU

BASH. новичок в этом деле, не могу понять в чем ошибка


0

1

нужно написать скрипт, который должен вывести список файлов, в первой строке которого находится заданное слово. Написал, но не работает, и ошибку тоже не выдает, подскажите в чем дело неопытному.

#!/bin/bash


search()


{

for file in ${WORKDIR} ; do
    if [ -r "$file" -a -f "$file" ]; then
    head -n 1 "$file" | grep -qi  "$KEYWORD" && echo "$file"
    fi
done

return

}



echo -n " Enter a search term: "


read KEYWORD


echo -n " Enter the path to the directory: "

read "WORKDIR"

search $KEYWORD $WORKDIR

exit


Ответ на: комментарий от quantum-troll

Функция не знает про твои переменные — аргументы доступны как $1...$N.

т.е. мне вместо $KEYWORD $WORKDIR в функции указать $1 $2 ?

skokov ()
Ответ на: комментарий от skokov

Да. И используй «$2/*» в цикле for:
[code=bash]
search() {
for file in «$2»/* ; do
if [ -r «$file» -a -f «$file» ]; then
head -n 1 «$file» | grep -qi «$1» && echo «$file»
fi
done

return
}
[/code]

quantum-troll ★★★★★ ()
Ответ на: комментарий от skokov
search() {
    for file in "$2"/* ; do
        if [ -r "$file" -a -f "$file" ]; then
            head -n 1 "$file" | grep -qi "$1" && echo "$file"
        fi
    done

    return
}

//ffix

quantum-troll ★★★★★ ()
Ответ на: комментарий от quantum-troll

Функция не знает про твои переменные

Неправда. Знает.

$ cat > test.sh
#!/bin/bash
a(){
echo $var1
var2=456
}
var1=123
a
echo $var2
$ chmod +x test.sh
$ ./test.sh 
123
456
$

generator ★★★ ()
Ответ на: комментарий от quantum-troll

bash, мне кажется, нужен не для того, чтобы думать категориями стоит/не стоит так делать. Если появляются такие мысли, bash стоит сразу выкидывать и браться за Python, как минимум.

generator ★★★ ()

echo -n " Enter a search term: "
read KEYWORD

//Fix
read -p " Enter a search term: " KEYWORD

ubuntuawp ★★ ()
Ответ на: комментарий от generator

Какой-то категоричный подход. Если можно написать более корретно, не размениваясь компактностью, почему нет.

anonymous ()
Ответ на: комментарий от anonymous

Да правильный подход же. Я по молодости тоже написал кучу всего на баше, уделяя внимание проектированию и корректности, но сейчас все поделки никуда не годны. Расширяемости никакой. Лучше бы уж в своё время потратил пару дней на книжку по нормальному ЯП.

Но опять же. Нисколько не умаляю достоинства баша, но для небольших задач, когда нужно сделать что-то СЕЙЧАС.

generator ★★★ ()
Ответ на: комментарий от quantum-troll

все работает:) спасибо:) а если совпадений не будет? то как об этом сообщить пользователю? создать еще одно условие?

skokov ()
Ответ на: комментарий от generator

уделяя внимание проектированию и корректности

В том-то и дело, что в _данном случае_ не надо уделять внимания, а просто прокинуть переменные.

anonymous ()
Ответ на: комментарий от skokov

Ну заведи флаг перед циклом. После grep добавить && установить флаг. И в конце return => ф-ию можно будет использовать в виде search .. || echo <smth>

anonymous ()
Ответ на: комментарий от quantum-troll

хороший пример

Видел, начиная с diri. Только смысл, лучше gitit поднять. А так предпочитаю dash, все-таки поближе к POSIX. Речь шла не об обязательно чем-то «немаленьком».

А ваш rc может и не дотестирован, и сколько будут поддерживать - неизвестно. А вообще для эстетов есть и http://github.com/frytvm/XS :)

anonymous ()
Ответ на: комментарий от anonymous

xs

Слишком раздутый. На самом деле, rc не хватает лишь некоторых фич, некоторые из которых реализованы в inferno shell.

quantum-troll ★★★★★ ()
Ответ на: комментарий от skokov

а можно сделать так, что бы вывело сообщение что таких файлов не найдено. Может условие добавить какое то?

в начале FC=0

после каждого файла (( FC++ ))

и в конце (( FC == 0 )) && echo «файлов нет»

PS: и да, в bash есть глобальные и локальные переменные. Локальные свои для каждой функции.

       Variables local to the function may be declared with the local builtin command.  Ordinarily, variables and  their  values
       are shared between the function and its caller.

       The  FUNCNEST  variable,  if  set  to a numeric value greater than 0, defines a maximum function nesting level.  Function
       invocations that exceed the limit cause the entire command to abort.

       If the builtin command return is executed in a function, the function completes and execution resumes with the next  com-
       mand  after the function call.  Any command associated with the RETURN trap is executed before execution resumes.  When a
       function completes, the values of the positional parameters and the special parameter # are restored to the  values  they
       had prior to the function's execution.

       Function  names  and  definitions  may  be  listed with the -f option to the declare or typeset builtin commands.  The -F
       option to declare or typeset will list the function names only (and optionally the source file and line  number,  if  the
       extdebug  shell option is enabled).  Functions may be exported so that subshells automatically have them defined with the
       -f option to the export builtin.  A function definition may be deleted using the -f option to the  unset  builtin.   Note
       that shell functions and variables with the same name may result in multiple identically-named entries in the environment
       passed to the shell's children.  Care should be taken in cases where this may cause a problem.

       Functions may be recursive.  The FUNCNEST variable may be used to limit the depth of the function call stack and restrict
       the number of function invocations.  By default, no limit is imposed on the number of recursive calls.
drBatty ★★ ()
Ответ на: комментарий от skokov

просто препод думаю к этому придерется, он любит это

правильно. Ещё 66 как код возврата верни. Так будет годно. Ну или ENOENT.

drBatty ★★ ()
Ответ на: комментарий от anonymous

Башизм на ровном месте..

ты перед тем как в топик зайти, сабж прочитай. А то прыщами от аллергии покроешься.

drBatty ★★ ()
Ответ на: комментарий от drBatty

Перечитай про _ровное место_, потом еще раз. Ладно бы что-нибудь упрощало, а мало того, что кривое - еще и башизм.

Если на вашем диалекте: уж не обижайся, но shell - не твое (по-крайней мере, чтобы «советовать»), иди обмазываться крестами (или сями, чем ты там любишь).

anonymous ()
Ответ на: комментарий от anonymous

Если на вашем диалекте: уж не обижайся, но shell - не твое (по-крайней мере, чтобы «советовать»)

я как-нить сам разберусь, что мне советовать. Речь про bash, явно сказано. В bash есть арифметика. Кто ты такой, что-бы её запрещать?

drBatty ★★ ()
Ответ на: комментарий от drBatty

Кто ты такой, что-бы её запрещать?

Где я ее «запрещал», еще раз повторить: «Башизм на _ровном месте.._» - сие намекает на неоправданные гвозди к bash.

Причем, повторюсь, что кривые, ибо 1-ых достаточно флага: BASH. новичок в этом деле, не могу понять в чем ошибка (комментарий) , возврат $(( ! found )) ; 2-ых - либо будет глобальная «FC», либо вывод сообщения в search (что тоже кривовато).

я как-нить сам разберусь, что мне советовать

Да вижу, что самостоятельный. За гостей сайта беспокоюсь же.

anonymous ()
Ответ на: комментарий от anonymous

ибо 1-ых достаточно флага

часто надо и ещё и посчитать, а не только флаг.

2-ых - либо будет глобальная «FC», либо вывод сообщения в search (что тоже кривовато).

что плохого в глобальной FC?

а вывод можно(и нужно) сделать в stderr.

За гостей сайта беспокоюсь же.

вот и я беспокоюсь, что они начнут строки складывать/вычитать, а потом удивляться, почему 3+5→'3+5', а не 8, как они ждали. Ну и приделывать какие-то жуткие костыли для сложения 3 и 5(dc например).

drBatty ★★ ()
Ответ на: комментарий от drBatty

часто надо и ещё и посчитать

Все же сомнтельный аргумента, почему бы тогда `dialog' не использовать, ведь «часто нужна возможность запуска не только из терминала»?

что плохого в глобальной FC?

Ничего особенно плохого. Но если не сложно можно обойтись без нее, почему нет.

либо вывод сообщения в _search_

(не, ну можно, конечно, локальная FC + обработка снаружи: делать return $FC, потом проверять $? - но это еще хуже)

а вывод можно(и нужно) сделать в _stderr_

вот и я беспокоюсь, что они начнут строки складывать/вычитать

арифметикой же не было, до вашего (( .. )), в posix вполне есть $(( .. )), лучше уж оставить bash-вариант для случая когда он действительно что-нибудь упрощает

anonymous ()
Ответ на: комментарий от anonymous

часто надо и ещё и посчитать

Все же сомнтельный аргумента, почему бы тогда `dialog' не использовать, ведь «часто нужна возможность запуска не только из терминала»?

dialog — сторонняя утилита, которой может и не быть, а bash есть в ТЗ и в первой строке скрипта ТСа. К тому-же с dialog у тебя могут возникнуть проблемы(решаемые) при запуске её например из screen.

Ничего особенно плохого. Но если не сложно можно обойтись без нее, почему нет.

если без неё и без $FLAG — почему нет? Но у тебя есть $FLAG. В шелле нет никаких булевых переменных, потому разница нулевая.

локальная FC + обработка снаружи

это-то ещё зачем? Код возврата не просто так нужен, это тебе не сишечка, в которой можно что угодно возвращать. В shell возвращать можнопринято лишь числа от 64 до 127. Да и то, это принято считать ошибкой.

арифметикой же не было

фиксация случая «обработано 0 файлов» подразумевает подсчёт этих файлов. ИМХО. Иначе вообще ничего выводить не нужно. Да, это ванга_мод.

drBatty ★★ ()
Ответ на: комментарий от drBatty

dialog — сторонняя утилита,

Мыслею по древу, очевидно, моя ремарка лишь ставила под сомнение добавление еще не затребованных возможностей, а-ля «счетчик». Какая разница dialog - не dialog?

В шелле нет никаких булевых переменных, потому _разница нулевая_

Вы внимательно читали: про search || echo <...>, как это сделать со счетчиком? (разумеется счетчик можно опустить его во флаг, но тогда зачем он)

это-то ещё зачем?

Иногда можно следить за веткой), еще раз: я аргументировал почему флаг _в данном случае_ представляется мне лучше счетчика либо: 1) счетчик глобален 2) локален, но обработка внутри search; теперь дополнил 3) локален, передается через return, добавив (*), что «это еще хуже» (потому что return /=0 для неуспешного возвращения, очевидно, нарушается логика).

В shell возвращать можнопринято лишь числа от 64 до 127.

Интересно, откуда инфа? А то ведь, return вполне может пробрасывать чужие (внешних комманд) коды с 1.

фиксация случая «обработано 0 файлов» подразумевает

А это, собственно, откуда? Или уже «часто надо и ещё и посчитать» таки-включено в задачу:

а можно сделать так, что бы вывело сообщение что таких файлов не найдено. Может условие добавить какое то?

anonymous ()
Ответ на: комментарий от anonymous

Да, это ванга_мод.

А вижу, откуда). Только удобно ли сидеть на двух стульях: то сей мод, то «сторонняя утилита».

anonymous ()
Ответ на: комментарий от anonymous

достало мну спорить. Если нужен флаг, пусть будет флаг. Я привёл более функциональный пример, пусть ТС сам думает что ЕМУ надо.

В shell возвращать можнопринято лишь числа от 64 до 127.

Интересно, откуда инфа? А то ведь, return вполне может пробрасывать чужие (внешних комманд) коды с 1.

на выходе имеем скрипт, который на ВСЕ ошибки отвечает 1. Даже на те, которые НЕ ошибки. Например эта search не нашла файлов, и вернула 1. И что? А вот если-бы она вернула 64, то это можно было проверить, и продолжить работу. Почему ≥64? Потому-что <64 зарезервировнны системой. В частности 1 команда ls отдаёт если

1 if minor problems (e.g., cannot access subdirectory)

А вот tar

1 `Some files differ'. If tar was invoked with `--compare' (`--diff', `-d') command line option, this means that some files in the archive differ from their disk counterparts (*note compare::). If tar was given `--create', `--append' or `--update' option, this exit code means that some files were changed while being archived and so the resulting archive does not contain the exact copy of the file set.

как видишь, смысл кода разный, и не всегда это ошибка. Иногда так оно и надо. Зависит от команды.

Коды ≥128 используются при прерывании программы каким-то сигналом.

drBatty ★★ ()
Ответ на: комментарий от drBatty

достало мну спорить. Если нужен флаг, пусть будет флаг. Я привёл более _функциональный_

Все просто: я заметил, что башизм -> была чрезмерная реакция -> я аргументировал за флаг -> ради «никнейма» пришлось балансировать на шаткой позиции. Подозреваю, что если бы общее число ваших комментов на лоре на что-нибудь не намекало, аргумент сорта «достало спорить» был бы раньше ^_^.

на выходе имеем скрипт, который на ВСЕ ошибки отвечает 1. Даже на те, которые НЕ ошибки. Например эта search не нашла файлов, и вернула 1. И что?

Это уже детали, вот когда понадобится различное поведение на различные коды возрата - тогда и можно, но что-то мне подсказывает, что это нужно лишь в малом количестве скриптов.

Коды ≥128 используются при прерывании программы каким-то сигналом.

Немного сомнительна такая категоричность: тут все-таки внутренние функции, почему бы и нет. Ссылочку бы на «best practice», хорошо буду искать.

anonymous ()
Ответ на: комментарий от anonymous

Все просто: я заметил, что башизм

блин, дык и что? И не просто «башизм», а «кривой башизм». Что и зацепило, ибо кривости в (( FC++ )) я до сих пор не понимаю. А то, что «башизм», я и не спорил.

Это уже детали, вот когда понадобится различное поведение на различные коды возрата - тогда и можно, но что-то мне подсказывает, что это нужно лишь в малом количестве скриптов.

вот когда чужой скрипт будешь использовать, который на любой чих 1 возвращает, тогда заговоришь по другому. Я не понимаю, сложно что-ли вернуть 64..127? Это и для отладки полезно, например в выхлопе лога код 83 сразу однозначно укажет на проблемное место. А что вы будете делать с кодом 1?

Немного сомнительна такая категоричность: тут все-таки внутренние функции, почему бы и нет. Ссылочку бы на «best practice», хорошо буду искать.

ссылку дам: man bash. Свои коды лучше не мешать с системными и с сигнальными, что-бы одного кода было достаточно для диагностики проблемы. И да, функции можно вызывать так: foo || exit, тогда в случае ошибки скрипт прервётся с кодом из функции, а в случае успеха всё будет работать. Просто, коротко, и ясно. Ну а какое-то число можно и в переменную записать.

drBatty ★★ ()
Ответ на: комментарий от drBatty

вот когда чужой скрипт будешь использовать, который на любой чих 1 возвращает, тогда заговоришь по другому

Что за «либеральные» приемы? Усиливаем высказывание оппонента, доводим его до абсурда, а потом героически опровергаем.

А что вы будете делать с кодом 1?

В _данном случае_ нужен еще один код? А то пока не вижу куда его применить. Или может фунционал уже по умолчанию расширен, и нужны коды для «directory doesn't exist / permission denied».

ссылку дам: man bash

Смотрел, про, что больше нельзя на нашел, ткните что ль. Зато видел «is greater than 128» для кодов второенных команд. Или нужно дать место сигналам с кодами аж больше 32?

Свои коды лучше не мешать с системными и с сигнальными

С этим-то кто спорит? Или покажите «мешанину».

anonymous ()
Ответ на: комментарий от drBatty

Что и зацепило, ибо кривости в (( FC++ )) я до сих пор не понимаю.

Ой забыл.. Нафига прибивать еще не прибитый скрипт, кода можно хоть: ": $(( a+=1 ))".

anonymous ()
Ответ на: комментарий от anonymous

Что за «либеральные» приемы? Усиливаем высказывание оппонента, доводим его до абсурда, а потом героически опровергаем.

это не демагогические приёмы, это лучи поноса от практика, а не демагогия от теоретика.

В _данном случае_ нужен еще один код? А то пока не вижу куда его применить. Или может фунционал уже по умолчанию расширен, и нужны коды для «directory doesn't exist / permission denied».

нужны. Точнее — желательны и для них какие-то коды, ну или хотя-бы просто завершение скрипта, если EACCESS || ENOENT.

Смотрел, про, что больше нельзя на нашел, ткните что ль. Зато видел «is greater than 128» для кодов второенных команд.

ну. Это прерывания. Потому твой код 130, будет равен коду команды, которую прервали (128+SIGINT). Потому код 130 лучше не использовать в своих скриптах как код возврата. Хотя — можешь, если любишь наступать на грабли.

Или покажите «мешанину».

системные <64, а сигнальные ≥128.

drBatty ★★ ()
Ответ на: комментарий от anonymous

Нафига прибивать еще не прибитый скрипт

откуда я знаю, зачем ТС написал в первой строке #!/bin/bash? Нравится ему так.

drBatty ★★ ()
Ответ на: комментарий от drBatty

который на любой чих 1 возвращает, тогда заговоришь по другому

это не демагогические приёмы, это лучи поноса от практика

И что за «практика», есть конкретный пример, где в нем «на любой чих»? Собственно поэтому и написал: «Усиливаем высказывание оппонента, доводим его до абсурда»

нужны. Точнее — желательны

Вот когда _понадобится_ - тогда и стоит прикручивать, пока он один - смысл, тем более, что будет желателен коммент, чтобы код не смотрелся как магическое число.

ну. Это прерывания. Потому твой код 130

Вы специально пропускаете важные места? (просто не в первый раз): «или нужно дать место сигналам с кодами аж больше 32?», читам, видим, что подразумевалось 128+32, так в чем трабла >160? (Это уж праздный интерес, раз такая категоричность - подумалось есть серьезные основания.)

системные <64, а сигнальные ≥128.

Ни сколь не пытаясь покуситься на ваши лавры практика, повторюсь, что имелся ввиду _данный пример_. Хорошо, допустим возвращаю из search() 1/0, с каким системным кодом (желательно, который _нужно_ обрабатывать) мешанина?

anonymous ()
Ответ на: комментарий от Delirium_veritas

А по-моему, так кош^Wтьфу православнее:

find <dir> -type f -exec awk -v pat=<regexp> '$0 ~ pat {print FILENAME} {nextfile}' {} +

anonymous ()
Ответ на: комментарий от anonymous

И что за «практика», есть конкретный пример, где в нем «на любой чих»? Собственно поэтому и написал: «Усиливаем высказывание оппонента, доводим его до абсурда»

зайди в любую тему, с любыми скриптами, и увидь код типа этого

run() {
  $*
  if [ $? -ne 0 ]
  then
    echo "$* failed with exit code $?"
    return 1
  else
    return 0
  fi
}

run command1 && run command2 && run command3

(вот первая попавшаяся ссылка из гугла: http://stackoverflow.com/questions/5195607/bash-beginner-check-exit-status )

Как видишь: скрипт на любой чих выдаёт код 1, и мало того, ещё и работает неправильно (т.к. команда [ портит код возврата).

Вот когда _понадобится_ - тогда и стоит прикручивать, пока он один - смысл, тем более, что будет желателен коммент, чтобы код не смотрелся как магическое число.

это скрипты. Там что угодно может случится, а работают они автономно.

Вы специально пропускаете важные места? (просто не в первый раз): «или нужно дать место сигналам с кодами аж больше 32?», читам, видим, что подразумевалось 128+32, так в чем трабла >160? (Это уж праздный интерес, раз такая категоричность - подумалось есть серьезные основания.)

мне лень искать место в документации, где написано, что именно с 64х. Если вам это так важно, и вы мне не верите: ищите сами. Оно есть, я его видел.

Ни сколь не пытаясь покуситься на ваши лавры практика, повторюсь, что имелся ввиду _данный пример_. Хорошо, допустим возвращаю из search() 1/0, с каким системным кодом (желательно, который _нужно_ обрабатывать) мешанина?

а что произойдёт, если в search произойдёт ENOENT?

drBatty ★★ ()
Ответ на: комментарий от drBatty

есть _конкретный пример_, где в нем «на любой чих»

вот первая попавшаяся ссылка из гугла:

И о же чем это говорит? В search внутренний цикл, а не единственный вызов, чтобы осмысленно пробрасывать коды - нужно сперва установить «как». Будто что нельзя найти примеров, где внешние счетчики становятся шибко непрозрачными, или где скрытый «rm -rf» - и тогда нужно сломя голову бежать и с чистой душой удалять shell.

видим, что подразумевалось 128+32

это скрипты. Там что угодно может случится, а работают они автономно.

Слишком широки аргумент, на мой взгляд: с таким подхом - лучше вообще скрптов не писать). Можно намек, чем все-таки чревато в данном случае?

мне лень искать место в документации, где написано, что именно с 64х

А где было про 64? Собственно, эта подветка была про коды >160, или вы так блестяще воспользовались «Это уж праздный интерес,»?

а что произойдёт, если в search произойдёт ENOENT?

Там _внутренний цикл_, и единственного возможного проброса кода от внутренних команд - нет: grep хоть на любую поломаную линку ругнется. Дык, как пробрасывать, когда на все ругнулось, когда хотя бы на одну, когда директории нет? (развернутый момент, упоминавшийся в первом абзаце сего коммента)

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.