LINUX.ORG.RU

bash, while read - странное поведение

 ,


0

1

добрый день

столкнулся со странным поведением bash-цикла

понятно, что мне что-то не понятно, вот хотелось бы уточнить, что именно :о)

run.sh

#!/bin/sh
set -e; clear

LST=line.lst

msg(){ echo -e "\n###\n$1, press ENTER to continue...\n###\n"; read; }

msg "msg DEBUG"

while read LINE
do
echo "echo  LINE = $LINE"
done < $LST

while read LINE
do
msg  "msg() LINE = $LINE"
done < $LST

echo -e "\n### OK ###"

line.lst

line_1
line_2
<blah-blah-blah...to> 
line_9

output

###
msg DEBUG, press ENTER to continue... ###!!! тут скрипт ожидает нажатия на ENTER
###

echo  LINE = line_0
echo  LINE = line_1
echo  LINE = line_2
echo  LINE = line_3
echo  LINE = line_4
echo  LINE = line_5
echo  LINE = line_6
echo  LINE = line_7
echo  LINE = line_8
echo  LINE = line_9

###
msg() LINE = line_0, press ENTER to continue... ###!!! тут скрипт проскакивает как угорелый
###

###
msg() LINE = line_2, press ENTER to continue... ###!!! аналогично
###

###
msg() LINE = line_4, press ENTER to continue... ###!!! ...
###

###
msg() LINE = line_6, press ENTER to continue... ###!!! ...
###

###
msg() LINE = line_8, press ENTER to continue... ###!!! ...
###

### OK ###

- в цикле не отрабатывается read/ожидание нажатия на ENTER

- отработка цикла (чтение файла) происходит с пропуском четных строк

...

slackware 12.2/14.2

p.s. видимо из-за использования read в цикле чтения файла ...

как бы так выкрутиться в таком случае?

- что бы функция msg() - всегда ожидала нажатия на ENTER

- что-бы цикл был без пропуска

★★★★

Последнее исправление: sunjob (всего исправлений: 3)

Внезапно. По-моему где-то в abs-guide даже было написано об этом  — читайте внимательней ко всяким комментариям. Ну или просто не делайте так.

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

если вы про «Advanced Bash-Scripting Guide» - то ни чего там нет по этому поводу ... (ну или я плохо читал... если есть, то можно ткнуть носом!)

Ну или просто не делайте так.

:o)))

нужно именно так, как в примере:

- использовать цикл чтения

- в цикле использовать функцию msg() с «ожиданием ввода/остановкой»

sunjob ★★★★
() автор топика

Этот ваш код делает read из LST, а не из stdin:

while read LINE
do
msg  "msg() LINE = $LINE"
done < $LST
Надо сделать так:
exec 9< "$LST"
while read -u 9 LINE
do
msg  "msg() LINE = $LINE"
done 
exec 9<&-

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

решил для удобства написания bash-скриптов с «аналогом» функции msg() - сделать бинарную версию

#include <ctype.h>
#include <stdint.h>
#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) 
////////////////////////////////////////////////////////////////////////////////
{
if(argc >= 2) 
  { 
  printf("###\n%s\n###\npress any key to continue...", argv[1]); 
  getchar(); 
  }
 
return 0;
}
////////////////////////////////////////////////////////////////////////////////

почти все нормально

запуск из bash-скрипта (все нормально)

$ ./run_bin.sh
###
Test message!
###
press any key to continue...
###
A B C !
###
press any key to continue...

запуск из ком.строки

$ ./msg.bin "A B C !"
bash: !": event not found

$ ./msg.bin "Й Ц У !"
>

+

траблы выявились на старом баше:

3.1.17(2) - older
4.3.48(1) - new

+

оборачивание msg/bin - в bash-скрипт, не помогает

msg bash-shell

#!/bin/sh

./msg.bin  $@
./msg.bin "$@"
./msg.bin "A B C !"
out
main$ msg "A B C !"
bash: !": event not found

отрабатывает только «непосредственная» установка параметра в «ковычках» (третья команда)

+

ИТОГО:

- если вызывать msg.bin из bash-скриптов, то все нормально
- если вызывать из ком.строки, то косяк на старом bash

если не сложно, волшебные пендили, ссылки, советы :о)

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 1)
Ответ на: комментарий от sunjob

если вызывать из ком.строки

то '!' - это манипуляция истории команд.

если не сложно, волшебные пендили

«Only backslash (\) and single quotes can quote the history expansion character.»

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

ну да... с одинарными ковычками все нормально (только константы)

но как тогда «разворачивать» переменные ...типа

msg.bin "$TMP !"

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

Какое слово вы не смогли перевести?

у меня проблема с буквами/символами а не словами :о)

если вызывать из ком.строки

то '!' - это манипуляция истории команд

для старого баша - монипуляция, а новый нормально относится к символу ! в строке... ???

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

для старого баша

на моём 4.2.45 тоже самое. Но в принципе, это явно выраженное дурацкое следование совместимости с баговой фичей. Ибо один знак ! без номера или второго ! ведь ничего не значит и действительно можно и подправить и слава богу, что это правят.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от vodz

вот и славно, кажется, поняли друг друга :о)

вообщем, не такая страшная беда, если принять за правило:

- использовать вызов msg.bin только из bash-скрипта

или

- использовать msg.bash-версию

не идеально, но жить можно!

спасибо

p.s. а баги, да, надо править!!!

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 2)
Ответ на: комментарий от teod0r

Что-то сомнительная фича. Выполнить случайную команду из истории, лол.

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

но как тогда «разворачивать» переменные ...типа

msg.bin «$TMP !»

Вы любите извр^w переменные?

$ _i_='!'
$ 
$ echo "$0 $_i_"
bash !
$
$ echo -e "test\x21"
test!

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

правда это - то еще удовольство

- специально заводить переменную
- набивать esc-код
но все равно - спасибо!

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

абалденный "справочник"

такой надо в офф-лайн виде! хтм-лька или пдф-ка... спасибо

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