LINUX.ORG.RU

bash-скрипты - работа с пайпами

 , ,


0

2

Доброго времени суток, aLL

Есть скрипт, отрабатывающий вот так:

script.sh [-a] filename

$1 - держит параметр -а (необязательный параметр)

$2 - имя обрабатываемого файла

Хочется иметь возможность делать вроде:

ls | script -a
Как я понимаю, для этого в скрипте нужно, используя read, читать аргументы командной строки и обрабатывать их. Но вот не пойму, в данном случае, какие именно и как?

Если возможно, закиньте пример своего скрипта, использующего пайп и строку его вызова.

Спасибо.

ЗЫЖ Хочу именно понять принцип написания шелл-скриптов с пайпами, про xargs в курсе.


Не совсем понимаю вопрос. Интересует, как именно читать данные построчно?

if [ -r "$file" ]; then input="$file"; else input=/dev/stdin; fi
while read variable; do
 process_line "$variable"
done < "$input"
(не проверял, могут быть ошибки)

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

Спасибо за ответ

Эм... Я в целом не понимаю, как именно писать скрипты, использующие пайп. Понятно, что для принятия из пайпа скрипт должен читать stdin, чтобы отдавать в пайп - писать в stdout. Но вот в примере:

script.sh -a filename

filename это второй параметр командной строки, он в переменной $2 а

ls | script.sh -a 
здесь как - тоже в $2? И как правильно в скрипте разбирать, что параметр может быть указан явно или передан через пайп (если вообще есть в этом разница)?

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

Через пайп никакие переменные не передаются. Он предназначен для передачи голых данных. Интерпретатор просто позволяет читать поступающие в stdin данные, а обрабатывать их надо самостоятельно — строки автоматически не разбиваются и никуда не распихиваются.

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

Я же показал: если файла нет (или можно сделать проверку $#), вместо файла берётся /dev/stdin - стандартный ввод, куда ls пишет данные.

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

Переменные не передаются, это понятно.

Как тогда, в вышеприведенном примере, передавать данные из пайпа как входной параметр командной строки скрипта? Чтобы

ls|script.sh -a

превратилось в пофайловое выполнение

script.sh -a file1
script.sh -a file2
.
.
script.sh -a fileN (где N - сколько ls выведет имен файлов)

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

Зачем тебе именно пайп вобще?
Смотри мой пример выше.

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

Да нет, не то, как бы объяснить....

Unix-way что гласит: утилита умеет делать что-то одно, но - хорошо. И утилиты можно связывать пайпами.

У меня есть скрипт, который делает одну нужную мне вещь. У него входной параметр - имя файла. И я хочу, чтобы он мог получать имя файла как в качестве параметра командной строки, так и через пайп, скажем, от вывода ls. Хочу иметь возможность делать вот так например:

ls|grep -i somevar|sort|script.sh -a

Так вот, как в моем скрипте обрабатывать параметры командной строки или как что где читать, чтобы можно было конструировать такие конструкции?

D_Ima
() автор топика
#!/bin/bash

function f() {
  echo "f($1)"
}

function stdin() {
  while read i; do
    f $i
  done
}

case $# in
  0)
    stdin
    exit 0
  ;;
  1)
    if [ "$1" == "-a" ]; then
      stdin
    else
      f $1
    fi
    exit 0
  ;;
  2)
    if [ "$1" == "-a" ]; then
      f $2
      exit 0
    fi
  ;;
esac

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

Ты все как-то суть не можешь ухватить.

$ cat p1.sh
#!/bin/bash

echo $1

$ ./p1.sh one
one

$ cat p2.sh
#!/bin/bash

read A
echo $A

$ echo "two" | ./p2.sh
two

$ ./p2.sh
<вводим с клавиатуры> three
three

$ ./p1.sh four | ./p2.sh
four

Ясно?

Kroz ★★★★★
()

я не понял полностью вопроса.
может тебе tee нужен ?

dada ★★★★★
()

Так а скрипт не принимает - в качестве stdin filename? Ну, то бишь ls | script -a - не отрабатывает как надо?

border-radius
()

Так и не поняли друг друга?

1. Используемые тобой внутри скрипта перенаправления (типа «<$2»после команды, или «cat $2 |» перед - если там такого нет см. п.2.) открывают файл по имени, только после этого его можно читать/писать. В случае «ls | скрипт» файл открывать уже не нужно, его сразу можно читать(неизменный кусок кода перед «<» или после «|»)

2. если там такого нет - ты обрабатываешь только *имя* файла(а не сам файл). В этом случае см. ответы выше про «while read»

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

Вместо тысячи слов...

Это оно, спасибо, добрый человек! Мозаика вроде сложилась...

2 aLL

Спасибо всем за помощь.
Трудно было объяснить, что конкретно было непонятно (суть не мог уловить), потому и просил пример скрипта. Но и другие ответы дополнили картину.

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

for file in *; do script -a $file; done

когда вы уже осилите pathname expansion

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